xref: /netbsd-src/external/gpl3/binutils.old/dist/bfd/som.c (revision 70f7362772ba52b749c976fb5e86e39a8b2c9afc)
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 unsigned long 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 	  bfd_size_type 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 	  bfd_size_type 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 	bfd_size_type 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 const bfd_target *
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 abfd->xvec;
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   bfd_size_type amt;
2083 
2084   /* First, read in space names.  */
2085   amt = file_hdr->space_strings_size;
2086   if (amt == (bfd_size_type) -1)
2087     {
2088       bfd_set_error (bfd_error_no_memory);
2089       goto error_return;
2090     }
2091   space_strings = bfd_malloc (amt + 1);
2092   if (space_strings == NULL && amt != 0)
2093     goto error_return;
2094 
2095   if (bfd_seek (abfd, current_offset + file_hdr->space_strings_location,
2096 		SEEK_SET) != 0)
2097     goto error_return;
2098   if (bfd_bread (space_strings, amt, abfd) != amt)
2099     goto error_return;
2100   /* Make sure that the string table is NUL terminated.  */
2101   space_strings[amt] = 0;
2102 
2103   /* Loop over all of the space dictionaries, building up sections.  */
2104   for (space_index = 0; space_index < file_hdr->space_total; space_index++)
2105     {
2106       struct som_space_dictionary_record space;
2107       struct som_external_space_dictionary_record ext_space;
2108       char *space_name;
2109       struct som_external_subspace_dictionary_record ext_subspace;
2110       struct som_subspace_dictionary_record subspace, save_subspace;
2111       unsigned int subspace_index;
2112       asection *space_asect;
2113       bfd_size_type space_size = 0;
2114       char *newname;
2115 
2116       /* Read the space dictionary element.  */
2117       if (bfd_seek (abfd,
2118 		    (current_offset + file_hdr->space_location
2119 		     + space_index * sizeof (ext_space)),
2120 		    SEEK_SET) != 0)
2121 	goto error_return;
2122       amt = sizeof ext_space;
2123       if (bfd_bread (&ext_space, amt, abfd) != amt)
2124 	goto error_return;
2125 
2126       som_swap_space_dictionary_in (&ext_space, &space);
2127 
2128       /* Setup the space name string.  */
2129       if (space.name >= file_hdr->space_strings_size)
2130 	goto error_return;
2131 
2132       space_name = space.name + space_strings;
2133 
2134       /* Make a section out of it.  */
2135       amt = strlen (space_name) + 1;
2136       newname = bfd_alloc (abfd, amt);
2137       if (!newname)
2138 	goto error_return;
2139       strcpy (newname, space_name);
2140 
2141       space_asect = bfd_make_section_anyway (abfd, newname);
2142       if (!space_asect)
2143 	goto error_return;
2144 
2145       if (space.is_loadable == 0)
2146 	space_asect->flags |= SEC_DEBUGGING;
2147 
2148       /* Set up all the attributes for the space.  */
2149       if (! bfd_som_set_section_attributes (space_asect, space.is_defined,
2150 					    space.is_private, space.sort_key,
2151 					    space.space_number))
2152 	goto error_return;
2153 
2154       /* If the space has no subspaces, then we're done.  */
2155       if (space.subspace_quantity == 0)
2156 	continue;
2157 
2158       /* Now, read in the first subspace for this space.  */
2159       if (bfd_seek (abfd,
2160 		    (current_offset + file_hdr->subspace_location
2161 		     + space.subspace_index * sizeof ext_subspace),
2162 		    SEEK_SET) != 0)
2163 	goto error_return;
2164       amt = sizeof ext_subspace;
2165       if (bfd_bread (&ext_subspace, amt, abfd) != amt)
2166 	goto error_return;
2167       /* Seek back to the start of the subspaces for loop below.  */
2168       if (bfd_seek (abfd,
2169 		    (current_offset + file_hdr->subspace_location
2170 		     + space.subspace_index * sizeof ext_subspace),
2171 		    SEEK_SET) != 0)
2172 	goto error_return;
2173 
2174       som_swap_subspace_dictionary_in (&ext_subspace, &subspace);
2175 
2176       /* Setup the start address and file loc from the first subspace
2177 	 record.  */
2178       space_asect->vma = subspace.subspace_start;
2179       space_asect->filepos = subspace.file_loc_init_value + current_offset;
2180       space_asect->alignment_power = exact_log2 (subspace.alignment);
2181       if (space_asect->alignment_power == (unsigned) -1)
2182 	goto error_return;
2183 
2184       /* Initialize save_subspace so we can reliably determine if this
2185 	 loop placed any useful values into it.  */
2186       memset (&save_subspace, 0, sizeof (save_subspace));
2187 
2188       /* Loop over the rest of the subspaces, building up more sections.  */
2189       for (subspace_index = 0; subspace_index < space.subspace_quantity;
2190 	   subspace_index++)
2191 	{
2192 	  asection *subspace_asect;
2193 	  char *subspace_name;
2194 
2195 	  /* Read in the next subspace.  */
2196 	  amt = sizeof ext_subspace;
2197 	  if (bfd_bread (&ext_subspace, amt, abfd) != amt)
2198 	    goto error_return;
2199 
2200 	  som_swap_subspace_dictionary_in (&ext_subspace, &subspace);
2201 
2202 	  /* Setup the subspace name string.  */
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   subspace_sections = bfd_malloc2 (total_subspaces, sizeof (asection *));
2348   if (subspace_sections == NULL)
2349     goto error_return;
2350 
2351   for (i = 0, section = abfd->sections; section; section = section->next)
2352     {
2353       if (!som_is_subspace (section))
2354 	continue;
2355 
2356       subspace_sections[i] = section;
2357       i++;
2358     }
2359   qsort (subspace_sections, total_subspaces,
2360 	 sizeof (asection *), compare_subspaces);
2361 
2362   /* subspace_sections is now sorted in the order in which the subspaces
2363      appear in the object file.  Assign an index to each one now.  */
2364   for (i = 0; i < total_subspaces; i++)
2365     subspace_sections[i]->target_index = i;
2366 
2367   if (space_strings != NULL)
2368     free (space_strings);
2369 
2370   if (subspace_sections != NULL)
2371     free (subspace_sections);
2372 
2373   return TRUE;
2374 
2375  error_return:
2376   if (space_strings != NULL)
2377     free (space_strings);
2378 
2379   if (subspace_sections != NULL)
2380     free (subspace_sections);
2381   return FALSE;
2382 }
2383 
2384 
2385 /* Read in a SOM object and make it into a BFD.  */
2386 
2387 static const bfd_target *
2388 som_object_p (bfd *abfd)
2389 {
2390   struct som_external_header ext_file_hdr;
2391   struct som_header file_hdr;
2392   struct som_exec_auxhdr *aux_hdr_ptr = NULL;
2393   unsigned long current_offset = 0;
2394   struct som_external_lst_header ext_lst_header;
2395   struct som_external_som_entry ext_som_entry;
2396   bfd_size_type amt;
2397   unsigned int loc;
2398 #define ENTRY_SIZE sizeof (struct som_external_som_entry)
2399 
2400   amt = sizeof (struct som_external_header);
2401   if (bfd_bread (&ext_file_hdr, amt, abfd) != amt)
2402     {
2403       if (bfd_get_error () != bfd_error_system_call)
2404 	bfd_set_error (bfd_error_wrong_format);
2405       return NULL;
2406     }
2407 
2408   som_swap_header_in (&ext_file_hdr, &file_hdr);
2409 
2410   if (!_PA_RISC_ID (file_hdr.system_id))
2411     {
2412       bfd_set_error (bfd_error_wrong_format);
2413       return NULL;
2414     }
2415 
2416   switch (file_hdr.a_magic)
2417     {
2418     case RELOC_MAGIC:
2419     case EXEC_MAGIC:
2420     case SHARE_MAGIC:
2421     case DEMAND_MAGIC:
2422     case DL_MAGIC:
2423     case SHL_MAGIC:
2424 #ifdef SHARED_MAGIC_CNX
2425     case SHARED_MAGIC_CNX:
2426 #endif
2427       break;
2428 
2429     case EXECLIBMAGIC:
2430       /* Read the lst header and determine where the SOM directory begins.  */
2431 
2432       if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
2433 	{
2434 	  if (bfd_get_error () != bfd_error_system_call)
2435 	    bfd_set_error (bfd_error_wrong_format);
2436 	  return NULL;
2437 	}
2438 
2439       amt = sizeof (struct som_external_lst_header);
2440       if (bfd_bread (&ext_lst_header, amt, abfd) != amt)
2441 	{
2442 	  if (bfd_get_error () != bfd_error_system_call)
2443 	    bfd_set_error (bfd_error_wrong_format);
2444 	  return NULL;
2445 	}
2446 
2447       /* Position to and read the first directory entry.  */
2448       loc = bfd_getb32 (ext_lst_header.dir_loc);
2449       if (bfd_seek (abfd, loc, SEEK_SET) != 0)
2450 	{
2451 	  if (bfd_get_error () != bfd_error_system_call)
2452 	    bfd_set_error (bfd_error_wrong_format);
2453 	  return NULL;
2454 	}
2455 
2456       amt = ENTRY_SIZE;
2457       if (bfd_bread (&ext_som_entry, amt, abfd) != amt)
2458 	{
2459 	  if (bfd_get_error () != bfd_error_system_call)
2460 	    bfd_set_error (bfd_error_wrong_format);
2461 	  return NULL;
2462 	}
2463 
2464       /* Now position to the first SOM.  */
2465       current_offset = bfd_getb32 (ext_som_entry.location);
2466       if (bfd_seek (abfd, current_offset, SEEK_SET) != 0)
2467 	{
2468 	  if (bfd_get_error () != bfd_error_system_call)
2469 	    bfd_set_error (bfd_error_wrong_format);
2470 	  return NULL;
2471 	}
2472 
2473       /* And finally, re-read the som header.  */
2474       amt = sizeof (struct som_external_header);
2475       if (bfd_bread (&ext_file_hdr, amt, abfd) != amt)
2476 	{
2477 	  if (bfd_get_error () != bfd_error_system_call)
2478 	    bfd_set_error (bfd_error_wrong_format);
2479 	  return NULL;
2480 	}
2481 
2482       som_swap_header_in (&ext_file_hdr, &file_hdr);
2483 
2484       break;
2485 
2486     default:
2487       bfd_set_error (bfd_error_wrong_format);
2488       return NULL;
2489     }
2490 
2491   if (file_hdr.version_id != OLD_VERSION_ID
2492       && file_hdr.version_id != NEW_VERSION_ID)
2493     {
2494       bfd_set_error (bfd_error_wrong_format);
2495       return NULL;
2496     }
2497 
2498   /* If the aux_header_size field in the file header is zero, then this
2499      object is an incomplete executable (a .o file).  Do not try to read
2500      a non-existant auxiliary header.  */
2501   if (file_hdr.aux_header_size != 0)
2502     {
2503       struct som_external_exec_auxhdr ext_exec_auxhdr;
2504 
2505       aux_hdr_ptr = bfd_zalloc (abfd,
2506 				(bfd_size_type) sizeof (*aux_hdr_ptr));
2507       if (aux_hdr_ptr == NULL)
2508 	return NULL;
2509       amt = sizeof (struct som_external_exec_auxhdr);
2510       if (bfd_bread (&ext_exec_auxhdr, amt, abfd) != amt)
2511 	{
2512 	  if (bfd_get_error () != bfd_error_system_call)
2513 	    bfd_set_error (bfd_error_wrong_format);
2514 	  return NULL;
2515 	}
2516       som_swap_exec_auxhdr_in (&ext_exec_auxhdr, aux_hdr_ptr);
2517     }
2518 
2519   if (!setup_sections (abfd, &file_hdr, current_offset))
2520     {
2521       /* setup_sections does not bubble up a bfd error code.  */
2522       bfd_set_error (bfd_error_bad_value);
2523       return NULL;
2524     }
2525 
2526   /* This appears to be a valid SOM object.  Do some initialization.  */
2527   return som_object_setup (abfd, &file_hdr, aux_hdr_ptr, current_offset);
2528 }
2529 
2530 /* Create a SOM object.  */
2531 
2532 static bfd_boolean
2533 som_mkobject (bfd *abfd)
2534 {
2535   /* Allocate memory to hold backend information.  */
2536   abfd->tdata.som_data = bfd_zalloc (abfd, (bfd_size_type) sizeof (struct som_data_struct));
2537   if (abfd->tdata.som_data == NULL)
2538     return FALSE;
2539   return TRUE;
2540 }
2541 
2542 /* Initialize some information in the file header.  This routine makes
2543    not attempt at doing the right thing for a full executable; it
2544    is only meant to handle relocatable objects.  */
2545 
2546 static bfd_boolean
2547 som_prep_headers (bfd *abfd)
2548 {
2549   struct som_header *file_hdr;
2550   asection *section;
2551   bfd_size_type amt = sizeof (struct som_header);
2552 
2553   /* Make and attach a file header to the BFD.  */
2554   file_hdr = bfd_zalloc (abfd, amt);
2555   if (file_hdr == NULL)
2556     return FALSE;
2557   obj_som_file_hdr (abfd) = file_hdr;
2558 
2559   if (abfd->flags & (EXEC_P | DYNAMIC))
2560     {
2561       /* Make and attach an exec header to the BFD.  */
2562       amt = sizeof (struct som_exec_auxhdr);
2563       obj_som_exec_hdr (abfd) = bfd_zalloc (abfd, amt);
2564       if (obj_som_exec_hdr (abfd) == NULL)
2565 	return FALSE;
2566 
2567       if (abfd->flags & D_PAGED)
2568 	file_hdr->a_magic = DEMAND_MAGIC;
2569       else if (abfd->flags & WP_TEXT)
2570 	file_hdr->a_magic = SHARE_MAGIC;
2571 #ifdef SHL_MAGIC
2572       else if (abfd->flags & DYNAMIC)
2573 	file_hdr->a_magic = SHL_MAGIC;
2574 #endif
2575       else
2576 	file_hdr->a_magic = EXEC_MAGIC;
2577     }
2578   else
2579     file_hdr->a_magic = RELOC_MAGIC;
2580 
2581   /* These fields are optional, and embedding timestamps is not always
2582      a wise thing to do, it makes comparing objects during a multi-stage
2583      bootstrap difficult.  */
2584   file_hdr->file_time.secs = 0;
2585   file_hdr->file_time.nanosecs = 0;
2586 
2587   file_hdr->entry_space = 0;
2588   file_hdr->entry_subspace = 0;
2589   file_hdr->entry_offset = 0;
2590   file_hdr->presumed_dp = 0;
2591 
2592   /* Now iterate over the sections translating information from
2593      BFD sections to SOM spaces/subspaces.  */
2594   for (section = abfd->sections; section != NULL; section = section->next)
2595     {
2596       /* Ignore anything which has not been marked as a space or
2597 	 subspace.  */
2598       if (!som_is_space (section) && !som_is_subspace (section))
2599 	continue;
2600 
2601       if (som_is_space (section))
2602 	{
2603 	  /* Allocate space for the space dictionary.  */
2604 	  amt = sizeof (struct som_space_dictionary_record);
2605 	  som_section_data (section)->space_dict = bfd_zalloc (abfd, amt);
2606 	  if (som_section_data (section)->space_dict == NULL)
2607 	    return FALSE;
2608 	  /* Set space attributes.  Note most attributes of SOM spaces
2609 	     are set based on the subspaces it contains.  */
2610 	  som_section_data (section)->space_dict->loader_fix_index = -1;
2611 	  som_section_data (section)->space_dict->init_pointer_index = -1;
2612 
2613 	  /* Set more attributes that were stuffed away in private data.  */
2614 	  som_section_data (section)->space_dict->sort_key =
2615 	    som_section_data (section)->copy_data->sort_key;
2616 	  som_section_data (section)->space_dict->is_defined =
2617 	    som_section_data (section)->copy_data->is_defined;
2618 	  som_section_data (section)->space_dict->is_private =
2619 	    som_section_data (section)->copy_data->is_private;
2620 	  som_section_data (section)->space_dict->space_number =
2621 	    som_section_data (section)->copy_data->space_number;
2622 	}
2623       else
2624 	{
2625 	  /* Allocate space for the subspace dictionary.  */
2626 	  amt = sizeof (struct som_subspace_dictionary_record);
2627 	  som_section_data (section)->subspace_dict = bfd_zalloc (abfd, amt);
2628 	  if (som_section_data (section)->subspace_dict == NULL)
2629 	    return FALSE;
2630 
2631 	  /* Set subspace attributes.  Basic stuff is done here, additional
2632 	     attributes are filled in later as more information becomes
2633 	     available.  */
2634 	  if (section->flags & SEC_ALLOC)
2635 	    som_section_data (section)->subspace_dict->is_loadable = 1;
2636 
2637 	  if (section->flags & SEC_CODE)
2638 	    som_section_data (section)->subspace_dict->code_only = 1;
2639 
2640 	  som_section_data (section)->subspace_dict->subspace_start =
2641 	    section->vma;
2642 	  som_section_data (section)->subspace_dict->subspace_length =
2643 	    section->size;
2644 	  som_section_data (section)->subspace_dict->initialization_length =
2645 	    section->size;
2646 	  som_section_data (section)->subspace_dict->alignment =
2647 	    1 << section->alignment_power;
2648 
2649 	  /* Set more attributes that were stuffed away in private data.  */
2650 	  som_section_data (section)->subspace_dict->sort_key =
2651 	    som_section_data (section)->copy_data->sort_key;
2652 	  som_section_data (section)->subspace_dict->access_control_bits =
2653 	    som_section_data (section)->copy_data->access_control_bits;
2654 	  som_section_data (section)->subspace_dict->quadrant =
2655 	    som_section_data (section)->copy_data->quadrant;
2656 	  som_section_data (section)->subspace_dict->is_comdat =
2657 	    som_section_data (section)->copy_data->is_comdat;
2658 	  som_section_data (section)->subspace_dict->is_common =
2659 	    som_section_data (section)->copy_data->is_common;
2660 	  som_section_data (section)->subspace_dict->dup_common =
2661 	    som_section_data (section)->copy_data->dup_common;
2662 	}
2663     }
2664   return TRUE;
2665 }
2666 
2667 /* Return TRUE if the given section is a SOM space, FALSE otherwise.  */
2668 
2669 static bfd_boolean
2670 som_is_space (asection *section)
2671 {
2672   /* If no copy data is available, then it's neither a space nor a
2673      subspace.  */
2674   if (som_section_data (section)->copy_data == NULL)
2675     return FALSE;
2676 
2677   /* If the containing space isn't the same as the given section,
2678      then this isn't a space.  */
2679   if (som_section_data (section)->copy_data->container != section
2680       && (som_section_data (section)->copy_data->container->output_section
2681 	  != section))
2682     return FALSE;
2683 
2684   /* OK.  Must be a space.  */
2685   return TRUE;
2686 }
2687 
2688 /* Return TRUE if the given section is a SOM subspace, FALSE otherwise.  */
2689 
2690 static bfd_boolean
2691 som_is_subspace (asection *section)
2692 {
2693   /* If no copy data is available, then it's neither a space nor a
2694      subspace.  */
2695   if (som_section_data (section)->copy_data == NULL)
2696     return FALSE;
2697 
2698   /* If the containing space is the same as the given section,
2699      then this isn't a subspace.  */
2700   if (som_section_data (section)->copy_data->container == section
2701       || (som_section_data (section)->copy_data->container->output_section
2702 	  == section))
2703     return FALSE;
2704 
2705   /* OK.  Must be a subspace.  */
2706   return TRUE;
2707 }
2708 
2709 /* Return TRUE if the given space contains the given subspace.  It
2710    is safe to assume space really is a space, and subspace really
2711    is a subspace.  */
2712 
2713 static bfd_boolean
2714 som_is_container (asection *space, asection *subspace)
2715 {
2716   return (som_section_data (subspace)->copy_data->container == space)
2717     || (som_section_data (subspace)->copy_data->container->output_section
2718 	== space);
2719 }
2720 
2721 /* Count and return the number of spaces attached to the given BFD.  */
2722 
2723 static unsigned long
2724 som_count_spaces (bfd *abfd)
2725 {
2726   int count = 0;
2727   asection *section;
2728 
2729   for (section = abfd->sections; section != NULL; section = section->next)
2730     count += som_is_space (section);
2731 
2732   return count;
2733 }
2734 
2735 /* Count the number of subspaces attached to the given BFD.  */
2736 
2737 static unsigned long
2738 som_count_subspaces (bfd *abfd)
2739 {
2740   int count = 0;
2741   asection *section;
2742 
2743   for (section = abfd->sections; section != NULL; section = section->next)
2744     count += som_is_subspace (section);
2745 
2746   return count;
2747 }
2748 
2749 /* Return -1, 0, 1 indicating the relative ordering of sym1 and sym2.
2750 
2751    We desire symbols to be ordered starting with the symbol with the
2752    highest relocation count down to the symbol with the lowest relocation
2753    count.  Doing so compacts the relocation stream.  */
2754 
2755 static int
2756 compare_syms (const void *arg1, const void *arg2)
2757 {
2758   asymbol **sym1 = (asymbol **) arg1;
2759   asymbol **sym2 = (asymbol **) arg2;
2760   unsigned int count1, count2;
2761 
2762   /* Get relocation count for each symbol.  Note that the count
2763      is stored in the udata pointer for section symbols!  */
2764   if ((*sym1)->flags & BSF_SECTION_SYM)
2765     count1 = (*sym1)->udata.i;
2766   else
2767     count1 = som_symbol_data (*sym1)->reloc_count;
2768 
2769   if ((*sym2)->flags & BSF_SECTION_SYM)
2770     count2 = (*sym2)->udata.i;
2771   else
2772     count2 = som_symbol_data (*sym2)->reloc_count;
2773 
2774   /* Return the appropriate value.  */
2775   if (count1 < count2)
2776     return 1;
2777   else if (count1 > count2)
2778     return -1;
2779   return 0;
2780 }
2781 
2782 /* Return -1, 0, 1 indicating the relative ordering of subspace1
2783    and subspace.  */
2784 
2785 static int
2786 compare_subspaces (const void *arg1, const void *arg2)
2787 {
2788   asection **subspace1 = (asection **) arg1;
2789   asection **subspace2 = (asection **) arg2;
2790 
2791   if ((*subspace1)->target_index < (*subspace2)->target_index)
2792     return -1;
2793   else if ((*subspace2)->target_index < (*subspace1)->target_index)
2794     return 1;
2795   else
2796     return 0;
2797 }
2798 
2799 /* Perform various work in preparation for emitting the fixup stream.  */
2800 
2801 static void
2802 som_prep_for_fixups (bfd *abfd, asymbol **syms, unsigned long num_syms)
2803 {
2804   unsigned long i;
2805   asection *section;
2806   asymbol **sorted_syms;
2807 
2808   /* Most SOM relocations involving a symbol have a length which is
2809      dependent on the index of the symbol.  So symbols which are
2810      used often in relocations should have a small index.  */
2811 
2812   /* First initialize the counters for each symbol.  */
2813   for (i = 0; i < num_syms; i++)
2814     {
2815       /* Handle a section symbol; these have no pointers back to the
2816 	 SOM symbol info.  So we just use the udata field to hold the
2817 	 relocation count.  */
2818       if (som_symbol_data (syms[i]) == NULL
2819 	  || syms[i]->flags & BSF_SECTION_SYM)
2820 	{
2821 	  syms[i]->flags |= BSF_SECTION_SYM;
2822 	  syms[i]->udata.i = 0;
2823 	}
2824       else
2825 	som_symbol_data (syms[i])->reloc_count = 0;
2826     }
2827 
2828   /* Now that the counters are initialized, make a weighted count
2829      of how often a given symbol is used in a relocation.  */
2830   for (section = abfd->sections; section != NULL; section = section->next)
2831     {
2832       int j;
2833 
2834       /* Does this section have any relocations?  */
2835       if ((int) section->reloc_count <= 0)
2836 	continue;
2837 
2838       /* Walk through each relocation for this section.  */
2839       for (j = 1; j < (int) section->reloc_count; j++)
2840 	{
2841 	  arelent *reloc = section->orelocation[j];
2842 	  int scale;
2843 
2844 	  /* A relocation against a symbol in the *ABS* section really
2845 	     does not have a symbol.  Likewise if the symbol isn't associated
2846 	     with any section.  */
2847 	  if (reloc->sym_ptr_ptr == NULL
2848 	      || bfd_is_abs_section ((*reloc->sym_ptr_ptr)->section))
2849 	    continue;
2850 
2851 	  /* Scaling to encourage symbols involved in R_DP_RELATIVE
2852 	     and R_CODE_ONE_SYMBOL relocations to come first.  These
2853 	     two relocations have single byte versions if the symbol
2854 	     index is very small.  */
2855 	  if (reloc->howto->type == R_DP_RELATIVE
2856 	      || reloc->howto->type == R_CODE_ONE_SYMBOL)
2857 	    scale = 2;
2858 	  else
2859 	    scale = 1;
2860 
2861 	  /* Handle section symbols by storing the count in the udata
2862 	     field.  It will not be used and the count is very important
2863 	     for these symbols.  */
2864 	  if ((*reloc->sym_ptr_ptr)->flags & BSF_SECTION_SYM)
2865 	    {
2866 	      (*reloc->sym_ptr_ptr)->udata.i =
2867 		(*reloc->sym_ptr_ptr)->udata.i + scale;
2868 	      continue;
2869 	    }
2870 
2871 	  /* A normal symbol.  Increment the count.  */
2872 	  som_symbol_data (*reloc->sym_ptr_ptr)->reloc_count += scale;
2873 	}
2874     }
2875 
2876   /* Sort a copy of the symbol table, rather than the canonical
2877      output symbol table.  */
2878   sorted_syms = bfd_zalloc2 (abfd, num_syms, sizeof (asymbol *));
2879   memcpy (sorted_syms, syms, num_syms * sizeof (asymbol *));
2880   qsort (sorted_syms, num_syms, sizeof (asymbol *), compare_syms);
2881   obj_som_sorted_syms (abfd) = sorted_syms;
2882 
2883   /* Compute the symbol indexes, they will be needed by the relocation
2884      code.  */
2885   for (i = 0; i < num_syms; i++)
2886     {
2887       /* A section symbol.  Again, there is no pointer to backend symbol
2888 	 information, so we reuse the udata field again.  */
2889       if (sorted_syms[i]->flags & BSF_SECTION_SYM)
2890 	sorted_syms[i]->udata.i = i;
2891       else
2892 	som_symbol_data (sorted_syms[i])->index = i;
2893     }
2894 }
2895 
2896 static bfd_boolean
2897 som_write_fixups (bfd *abfd,
2898 		  unsigned long current_offset,
2899 		  unsigned int *total_reloc_sizep)
2900 {
2901   unsigned int i, j;
2902   /* Chunk of memory that we can use as buffer space, then throw
2903      away.  */
2904   unsigned char tmp_space[SOM_TMP_BUFSIZE];
2905   unsigned char *p;
2906   unsigned int total_reloc_size = 0;
2907   unsigned int subspace_reloc_size = 0;
2908   unsigned int num_spaces = obj_som_file_hdr (abfd)->space_total;
2909   asection *section = abfd->sections;
2910   bfd_size_type amt;
2911 
2912   memset (tmp_space, 0, SOM_TMP_BUFSIZE);
2913   p = tmp_space;
2914 
2915   /* All the fixups for a particular subspace are emitted in a single
2916      stream.  All the subspaces for a particular space are emitted
2917      as a single stream.
2918 
2919      So, to get all the locations correct one must iterate through all the
2920      spaces, for each space iterate through its subspaces and output a
2921      fixups stream.  */
2922   for (i = 0; i < num_spaces; i++)
2923     {
2924       asection *subsection;
2925 
2926       /* Find a space.  */
2927       while (!som_is_space (section))
2928 	section = section->next;
2929 
2930       /* Now iterate through each of its subspaces.  */
2931       for (subsection = abfd->sections;
2932 	   subsection != NULL;
2933 	   subsection = subsection->next)
2934 	{
2935 	  int reloc_offset;
2936 	  unsigned int current_rounding_mode;
2937 #ifndef NO_PCREL_MODES
2938 	  unsigned int current_call_mode;
2939 #endif
2940 
2941 	  /* Find a subspace of this space.  */
2942 	  if (!som_is_subspace (subsection)
2943 	      || !som_is_container (section, subsection))
2944 	    continue;
2945 
2946 	  /* If this subspace does not have real data, then we are
2947 	     finished with it.  */
2948 	  if ((subsection->flags & SEC_HAS_CONTENTS) == 0)
2949 	    {
2950 	      som_section_data (subsection)->subspace_dict->fixup_request_index
2951 		= -1;
2952 	      continue;
2953 	    }
2954 
2955 	  /* This subspace has some relocations.  Put the relocation stream
2956 	     index into the subspace record.  */
2957 	  som_section_data (subsection)->subspace_dict->fixup_request_index
2958 	    = total_reloc_size;
2959 
2960 	  /* To make life easier start over with a clean slate for
2961 	     each subspace.  Seek to the start of the relocation stream
2962 	     for this subspace in preparation for writing out its fixup
2963 	     stream.  */
2964 	  if (bfd_seek (abfd, current_offset + total_reloc_size, SEEK_SET) != 0)
2965 	    return FALSE;
2966 
2967 	  /* Buffer space has already been allocated.  Just perform some
2968 	     initialization here.  */
2969 	  p = tmp_space;
2970 	  subspace_reloc_size = 0;
2971 	  reloc_offset = 0;
2972 	  som_initialize_reloc_queue (reloc_queue);
2973 	  current_rounding_mode = R_N_MODE;
2974 #ifndef NO_PCREL_MODES
2975 	  current_call_mode = R_SHORT_PCREL_MODE;
2976 #endif
2977 
2978 	  /* Translate each BFD relocation into one or more SOM
2979 	     relocations.  */
2980 	  for (j = 0; j < subsection->reloc_count; j++)
2981 	    {
2982 	      arelent *bfd_reloc = subsection->orelocation[j];
2983 	      unsigned int skip;
2984 	      int sym_num;
2985 
2986 	      /* Get the symbol number.  Remember it's stored in a
2987 		 special place for section symbols.  */
2988 	      if ((*bfd_reloc->sym_ptr_ptr)->flags & BSF_SECTION_SYM)
2989 		sym_num = (*bfd_reloc->sym_ptr_ptr)->udata.i;
2990 	      else
2991 		sym_num = som_symbol_data (*bfd_reloc->sym_ptr_ptr)->index;
2992 
2993 	      /* If there is not enough room for the next couple relocations,
2994 		 then dump the current buffer contents now.  Also reinitialize
2995 		 the relocation queue.
2996 
2997 		 No single BFD relocation could ever translate into more
2998 		 than 100 bytes of SOM relocations (20bytes is probably the
2999 		 upper limit, but leave lots of space for growth).  */
3000 	      if (p - tmp_space + 100 > SOM_TMP_BUFSIZE)
3001 		{
3002 		  amt = p - tmp_space;
3003 		  if (bfd_bwrite ((void *) tmp_space, amt, abfd) != amt)
3004 		    return FALSE;
3005 
3006 		  p = tmp_space;
3007 		  som_initialize_reloc_queue (reloc_queue);
3008 		}
3009 
3010 	      /* Emit R_NO_RELOCATION fixups to map any bytes which were
3011 		 skipped.  */
3012 	      skip = bfd_reloc->address - reloc_offset;
3013 	      p = som_reloc_skip (abfd, skip, p,
3014 				  &subspace_reloc_size, reloc_queue);
3015 
3016 	      /* Update reloc_offset for the next iteration.
3017 
3018 		 Many relocations do not consume input bytes.  They
3019 		 are markers, or set state necessary to perform some
3020 		 later relocation.  */
3021 	      switch (bfd_reloc->howto->type)
3022 		{
3023 		case R_ENTRY:
3024 		case R_ALT_ENTRY:
3025 		case R_EXIT:
3026 		case R_N_MODE:
3027 		case R_S_MODE:
3028 		case R_D_MODE:
3029 		case R_R_MODE:
3030 		case R_FSEL:
3031 		case R_LSEL:
3032 		case R_RSEL:
3033 		case R_COMP1:
3034 		case R_COMP2:
3035 		case R_BEGIN_BRTAB:
3036 		case R_END_BRTAB:
3037 		case R_BEGIN_TRY:
3038 		case R_END_TRY:
3039 		case R_N0SEL:
3040 		case R_N1SEL:
3041 #ifndef NO_PCREL_MODES
3042 		case R_SHORT_PCREL_MODE:
3043 		case R_LONG_PCREL_MODE:
3044 #endif
3045 		  reloc_offset = bfd_reloc->address;
3046 		  break;
3047 
3048 		default:
3049 		  reloc_offset = bfd_reloc->address + 4;
3050 		  break;
3051 		}
3052 
3053 	      /* Now the actual relocation we care about.  */
3054 	      switch (bfd_reloc->howto->type)
3055 		{
3056 		case R_PCREL_CALL:
3057 		case R_ABS_CALL:
3058 		  p = som_reloc_call (abfd, p, &subspace_reloc_size,
3059 				      bfd_reloc, sym_num, reloc_queue);
3060 		  break;
3061 
3062 		case R_CODE_ONE_SYMBOL:
3063 		case R_DP_RELATIVE:
3064 		  /* Account for any addend.  */
3065 		  if (bfd_reloc->addend)
3066 		    p = som_reloc_addend (abfd, bfd_reloc->addend, p,
3067 					  &subspace_reloc_size, reloc_queue);
3068 
3069 		  if (sym_num < 0x20)
3070 		    {
3071 		      bfd_put_8 (abfd, bfd_reloc->howto->type + sym_num, p);
3072 		      subspace_reloc_size += 1;
3073 		      p += 1;
3074 		    }
3075 		  else if (sym_num < 0x100)
3076 		    {
3077 		      bfd_put_8 (abfd, bfd_reloc->howto->type + 32, p);
3078 		      bfd_put_8 (abfd, sym_num, p + 1);
3079 		      p = try_prev_fixup (abfd, &subspace_reloc_size, p,
3080 					  2, reloc_queue);
3081 		    }
3082 		  else if (sym_num < 0x10000000)
3083 		    {
3084 		      bfd_put_8 (abfd, bfd_reloc->howto->type + 33, p);
3085 		      bfd_put_8 (abfd, sym_num >> 16, p + 1);
3086 		      bfd_put_16 (abfd, (bfd_vma) sym_num, p + 2);
3087 		      p = try_prev_fixup (abfd, &subspace_reloc_size,
3088 					  p, 4, reloc_queue);
3089 		    }
3090 		  else
3091 		    abort ();
3092 		  break;
3093 
3094 		case R_DATA_GPREL:
3095 		  /* Account for any addend.  */
3096 		  if (bfd_reloc->addend)
3097 		    p = som_reloc_addend (abfd, bfd_reloc->addend, p,
3098 					  &subspace_reloc_size, reloc_queue);
3099 
3100 		  if (sym_num < 0x10000000)
3101 		    {
3102 		      bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3103 		      bfd_put_8 (abfd, sym_num >> 16, p + 1);
3104 		      bfd_put_16 (abfd, (bfd_vma) sym_num, p + 2);
3105 		      p = try_prev_fixup (abfd, &subspace_reloc_size,
3106 					  p, 4, reloc_queue);
3107 		    }
3108 		  else
3109 		    abort ();
3110 		  break;
3111 
3112 		case R_DATA_ONE_SYMBOL:
3113 		case R_DATA_PLABEL:
3114 		case R_CODE_PLABEL:
3115 		case R_DLT_REL:
3116 		  /* Account for any addend using R_DATA_OVERRIDE.  */
3117 		  if (bfd_reloc->howto->type != R_DATA_ONE_SYMBOL
3118 		      && bfd_reloc->addend)
3119 		    p = som_reloc_addend (abfd, bfd_reloc->addend, p,
3120 					  &subspace_reloc_size, reloc_queue);
3121 
3122 		  if (sym_num < 0x100)
3123 		    {
3124 		      bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3125 		      bfd_put_8 (abfd, sym_num, p + 1);
3126 		      p = try_prev_fixup (abfd, &subspace_reloc_size, p,
3127 					  2, reloc_queue);
3128 		    }
3129 		  else if (sym_num < 0x10000000)
3130 		    {
3131 		      bfd_put_8 (abfd, bfd_reloc->howto->type + 1, p);
3132 		      bfd_put_8 (abfd, sym_num >> 16, p + 1);
3133 		      bfd_put_16 (abfd, (bfd_vma) sym_num, p + 2);
3134 		      p = try_prev_fixup (abfd, &subspace_reloc_size,
3135 					  p, 4, reloc_queue);
3136 		    }
3137 		  else
3138 		    abort ();
3139 		  break;
3140 
3141 		case R_ENTRY:
3142 		  {
3143 		    unsigned int tmp;
3144 		    arelent *tmp_reloc = NULL;
3145 		    bfd_put_8 (abfd, R_ENTRY, p);
3146 
3147 		    /* R_ENTRY relocations have 64 bits of associated
3148 		       data.  Unfortunately the addend field of a bfd
3149 		       relocation is only 32 bits.  So, we split up
3150 		       the 64bit unwind information and store part in
3151 		       the R_ENTRY relocation, and the rest in the R_EXIT
3152 		       relocation.  */
3153 		    bfd_put_32 (abfd, bfd_reloc->addend, p + 1);
3154 
3155 		    /* Find the next R_EXIT relocation.  */
3156 		    for (tmp = j; tmp < subsection->reloc_count; tmp++)
3157 		      {
3158 			tmp_reloc = subsection->orelocation[tmp];
3159 			if (tmp_reloc->howto->type == R_EXIT)
3160 			  break;
3161 		      }
3162 
3163 		    if (tmp == subsection->reloc_count)
3164 		      abort ();
3165 
3166 		    bfd_put_32 (abfd, tmp_reloc->addend, p + 5);
3167 		    p = try_prev_fixup (abfd, &subspace_reloc_size,
3168 					p, 9, reloc_queue);
3169 		    break;
3170 		  }
3171 
3172 		case R_N_MODE:
3173 		case R_S_MODE:
3174 		case R_D_MODE:
3175 		case R_R_MODE:
3176 		  /* If this relocation requests the current rounding
3177 		     mode, then it is redundant.  */
3178 		  if (bfd_reloc->howto->type != current_rounding_mode)
3179 		    {
3180 		      bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3181 		      subspace_reloc_size += 1;
3182 		      p += 1;
3183 		      current_rounding_mode = bfd_reloc->howto->type;
3184 		    }
3185 		  break;
3186 
3187 #ifndef NO_PCREL_MODES
3188 		case R_LONG_PCREL_MODE:
3189 		case R_SHORT_PCREL_MODE:
3190 		  if (bfd_reloc->howto->type != current_call_mode)
3191 		    {
3192 		      bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3193 		      subspace_reloc_size += 1;
3194 		      p += 1;
3195 		      current_call_mode = bfd_reloc->howto->type;
3196 		    }
3197 		  break;
3198 #endif
3199 
3200 		case R_EXIT:
3201 		case R_ALT_ENTRY:
3202 		case R_FSEL:
3203 		case R_LSEL:
3204 		case R_RSEL:
3205 		case R_BEGIN_BRTAB:
3206 		case R_END_BRTAB:
3207 		case R_BEGIN_TRY:
3208 		case R_N0SEL:
3209 		case R_N1SEL:
3210 		  bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3211 		  subspace_reloc_size += 1;
3212 		  p += 1;
3213 		  break;
3214 
3215 		case R_END_TRY:
3216 		  /* The end of an exception handling region.  The reloc's
3217 		     addend contains the offset of the exception handling
3218 		     code.  */
3219 		  if (bfd_reloc->addend == 0)
3220 		    bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3221 		  else if (bfd_reloc->addend < 1024)
3222 		    {
3223 		      bfd_put_8 (abfd, bfd_reloc->howto->type + 1, p);
3224 		      bfd_put_8 (abfd, bfd_reloc->addend / 4, p + 1);
3225 		      p = try_prev_fixup (abfd, &subspace_reloc_size,
3226 					  p, 2, reloc_queue);
3227 		    }
3228 		  else
3229 		    {
3230 		      bfd_put_8 (abfd, bfd_reloc->howto->type + 2, p);
3231 		      bfd_put_8 (abfd, (bfd_reloc->addend / 4) >> 16, p + 1);
3232 		      bfd_put_16 (abfd, bfd_reloc->addend / 4, p + 2);
3233 		      p = try_prev_fixup (abfd, &subspace_reloc_size,
3234 					  p, 4, reloc_queue);
3235 		    }
3236 		  break;
3237 
3238 		case R_COMP1:
3239 		  /* The only time we generate R_COMP1, R_COMP2 and
3240 		     R_CODE_EXPR relocs is for the difference of two
3241 		     symbols.  Hence we can cheat here.  */
3242 		  bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3243 		  bfd_put_8 (abfd, 0x44, p + 1);
3244 		  p = try_prev_fixup (abfd, &subspace_reloc_size,
3245 				      p, 2, reloc_queue);
3246 		  break;
3247 
3248 		case R_COMP2:
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, 0x80, p + 1);
3254 		  bfd_put_8 (abfd, sym_num >> 16, p + 2);
3255 		  bfd_put_16 (abfd, (bfd_vma) sym_num, p + 3);
3256 		  p = try_prev_fixup (abfd, &subspace_reloc_size,
3257 				      p, 5, reloc_queue);
3258 		  break;
3259 
3260 		case R_CODE_EXPR:
3261 		case R_DATA_EXPR:
3262 		  /* The only time we generate R_COMP1, R_COMP2 and
3263 		     R_CODE_EXPR relocs is for the difference of two
3264 		     symbols.  Hence we can cheat here.  */
3265 		  bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3266 		  subspace_reloc_size += 1;
3267 		  p += 1;
3268 		  break;
3269 
3270 		/* Put a "R_RESERVED" relocation in the stream if
3271 		   we hit something we do not understand.  The linker
3272 		   will complain loudly if this ever happens.  */
3273 		default:
3274 		  bfd_put_8 (abfd, 0xff, p);
3275 		  subspace_reloc_size += 1;
3276 		  p += 1;
3277 		  break;
3278 		}
3279 	    }
3280 
3281 	  /* Last BFD relocation for a subspace has been processed.
3282 	     Map the rest of the subspace with R_NO_RELOCATION fixups.  */
3283 	  p = som_reloc_skip (abfd, subsection->size - reloc_offset,
3284 			      p, &subspace_reloc_size, reloc_queue);
3285 
3286 	  /* Scribble out the relocations.  */
3287 	  amt = p - tmp_space;
3288 	  if (bfd_bwrite ((void *) tmp_space, amt, abfd) != amt)
3289 	    return FALSE;
3290 	  p = tmp_space;
3291 
3292 	  total_reloc_size += subspace_reloc_size;
3293 	  som_section_data (subsection)->subspace_dict->fixup_request_quantity
3294 	    = subspace_reloc_size;
3295 	}
3296       section = section->next;
3297     }
3298   *total_reloc_sizep = total_reloc_size;
3299   return TRUE;
3300 }
3301 
3302 /* Write out the space/subspace string table.  */
3303 
3304 static bfd_boolean
3305 som_write_space_strings (bfd *abfd,
3306 			 unsigned long current_offset,
3307 			 unsigned int *string_sizep)
3308 {
3309   /* Chunk of memory that we can use as buffer space, then throw
3310      away.  */
3311   size_t tmp_space_size = SOM_TMP_BUFSIZE;
3312   char *tmp_space = bfd_malloc (tmp_space_size);
3313   char *p = tmp_space;
3314   unsigned int strings_size = 0;
3315   asection *section;
3316   bfd_size_type amt;
3317   bfd_size_type res;
3318 
3319   if (tmp_space == NULL)
3320     return FALSE;
3321 
3322   /* Seek to the start of the space strings in preparation for writing
3323      them out.  */
3324   if (bfd_seek (abfd, (file_ptr) current_offset, SEEK_SET) != 0)
3325     return FALSE;
3326 
3327   /* Walk through all the spaces and subspaces (order is not important)
3328      building up and writing string table entries for their names.  */
3329   for (section = abfd->sections; section != NULL; section = section->next)
3330     {
3331       size_t length;
3332 
3333       /* Only work with space/subspaces; avoid any other sections
3334 	 which might have been made (.text for example).  */
3335       if (!som_is_space (section) && !som_is_subspace (section))
3336 	continue;
3337 
3338       /* Get the length of the space/subspace name.  */
3339       length = strlen (section->name);
3340 
3341       /* If there is not enough room for the next entry, then dump the
3342 	 current buffer contents now and maybe allocate a larger
3343 	 buffer.  Each entry will take 4 bytes to hold the string
3344 	 length + the string itself + null terminator.  */
3345       if (p - tmp_space + 5 + length > tmp_space_size)
3346 	{
3347 	  /* Flush buffer before refilling or reallocating.  */
3348 	  amt = p - tmp_space;
3349 	  if (bfd_bwrite ((void *) &tmp_space[0], amt, abfd) != amt)
3350 	    return FALSE;
3351 
3352 	  /* Reallocate if now empty buffer still too small.  */
3353 	  if (5 + length > tmp_space_size)
3354 	    {
3355 	      /* Ensure a minimum growth factor to avoid O(n**2) space
3356 		 consumption for n strings.  The optimal minimum
3357 		 factor seems to be 2, as no other value can guarantee
3358 		 wasting less than 50% space.  (Note that we cannot
3359 		 deallocate space allocated by `alloca' without
3360 		 returning from this function.)  The same technique is
3361 		 used a few more times below when a buffer is
3362 		 reallocated.  */
3363 	      if (2 * tmp_space_size < length + 5)
3364 		tmp_space_size = length + 5;
3365 	      else
3366 		tmp_space_size = 2 * tmp_space_size;
3367 	      tmp_space = xrealloc (tmp_space, tmp_space_size);
3368 	    }
3369 
3370 	  /* Reset to beginning of the (possibly new) buffer space.  */
3371 	  p = tmp_space;
3372 	}
3373 
3374       /* First element in a string table entry is the length of the
3375 	 string.  Alignment issues are already handled.  */
3376       bfd_put_32 (abfd, (bfd_vma) length, p);
3377       p += 4;
3378       strings_size += 4;
3379 
3380       /* Record the index in the space/subspace records.  */
3381       if (som_is_space (section))
3382 	som_section_data (section)->space_dict->name = strings_size;
3383       else
3384 	som_section_data (section)->subspace_dict->name = strings_size;
3385 
3386       /* Next comes the string itself + a null terminator.  */
3387       strcpy (p, section->name);
3388       p += length + 1;
3389       strings_size += length + 1;
3390 
3391       /* Always align up to the next word boundary.  */
3392       while (strings_size % 4)
3393 	{
3394 	  bfd_put_8 (abfd, 0, p);
3395 	  p++;
3396 	  strings_size++;
3397 	}
3398     }
3399 
3400   /* Done with the space/subspace strings.  Write out any information
3401      contained in a partial block.  */
3402   amt = p - tmp_space;
3403   res = bfd_bwrite ((void *) &tmp_space[0], amt, abfd);
3404   free (tmp_space);
3405   if (res != amt)
3406     return FALSE;
3407   *string_sizep = strings_size;
3408   return TRUE;
3409 }
3410 
3411 /* Write out the symbol string table.  */
3412 
3413 static bfd_boolean
3414 som_write_symbol_strings (bfd *abfd,
3415 			  unsigned long current_offset,
3416 			  asymbol **syms,
3417 			  unsigned int num_syms,
3418 			  unsigned int *string_sizep,
3419 			  struct som_compilation_unit *compilation_unit)
3420 {
3421   unsigned int i;
3422   /* Chunk of memory that we can use as buffer space, then throw
3423      away.  */
3424   size_t tmp_space_size = SOM_TMP_BUFSIZE;
3425   char *tmp_space = bfd_malloc (tmp_space_size);
3426   char *p = tmp_space;
3427   unsigned int strings_size = 0;
3428   bfd_size_type amt;
3429   bfd_size_type res;
3430 
3431   if (tmp_space == NULL)
3432     return FALSE;
3433 
3434   /* This gets a bit gruesome because of the compilation unit.  The
3435      strings within the compilation unit are part of the symbol
3436      strings, but don't have symbol_dictionary entries.  So, manually
3437      write them and update the compilation unit header.  On input, the
3438      compilation unit header contains local copies of the strings.
3439      Move them aside.  */
3440 
3441   /* Seek to the start of the space strings in preparation for writing
3442      them out.  */
3443   if (bfd_seek (abfd, (file_ptr) current_offset, SEEK_SET) != 0)
3444     return FALSE;
3445 
3446   if (compilation_unit)
3447     {
3448       for (i = 0; i < 4; i++)
3449 	{
3450 	  struct som_name_pt *name;
3451 	  size_t length;
3452 
3453 	  switch (i)
3454 	    {
3455 	    case 0:
3456 	      name = &compilation_unit->name;
3457 	      break;
3458 	    case 1:
3459 	      name = &compilation_unit->language_name;
3460 	      break;
3461 	    case 2:
3462 	      name = &compilation_unit->product_id;
3463 	      break;
3464 	    case 3:
3465 	      name = &compilation_unit->version_id;
3466 	      break;
3467 	    default:
3468 	      abort ();
3469 	    }
3470 
3471 	  length = strlen (name->name);
3472 
3473 	  /* If there is not enough room for the next entry, then dump
3474 	     the current buffer contents now and maybe allocate a
3475 	     larger buffer.  */
3476 	  if (p - tmp_space + 5 + length > tmp_space_size)
3477 	    {
3478 	      /* Flush buffer before refilling or reallocating.  */
3479 	      amt = p - tmp_space;
3480 	      if (bfd_bwrite ((void *) &tmp_space[0], amt, abfd) != amt)
3481 		return FALSE;
3482 
3483 	      /* Reallocate if now empty buffer still too small.  */
3484 	      if (5 + length > tmp_space_size)
3485 		{
3486 		  /* See alloca above for discussion of new size.  */
3487 		  if (2 * tmp_space_size < 5 + length)
3488 		    tmp_space_size = 5 + length;
3489 		  else
3490 		    tmp_space_size = 2 * tmp_space_size;
3491 		  tmp_space = xrealloc (tmp_space, tmp_space_size);
3492 		}
3493 
3494 	      /* Reset to beginning of the (possibly new) buffer
3495 		 space.  */
3496 	      p = tmp_space;
3497 	    }
3498 
3499 	  /* First element in a string table entry is the length of
3500 	     the string.  This must always be 4 byte aligned.  This is
3501 	     also an appropriate time to fill in the string index
3502 	     field in the symbol table entry.  */
3503 	  bfd_put_32 (abfd, (bfd_vma) length, p);
3504 	  strings_size += 4;
3505 	  p += 4;
3506 
3507 	  /* Next comes the string itself + a null terminator.  */
3508 	  strcpy (p, name->name);
3509 
3510 	  name->strx = strings_size;
3511 
3512 	  p += length + 1;
3513 	  strings_size += length + 1;
3514 
3515 	  /* Always align up to the next word boundary.  */
3516 	  while (strings_size % 4)
3517 	    {
3518 	      bfd_put_8 (abfd, 0, p);
3519 	      strings_size++;
3520 	      p++;
3521 	    }
3522 	}
3523     }
3524 
3525   for (i = 0; i < num_syms; i++)
3526     {
3527       size_t length = strlen (syms[i]->name);
3528 
3529       /* If there is not enough room for the next entry, then dump the
3530 	 current buffer contents now and maybe allocate a larger buffer.  */
3531      if (p - tmp_space + 5 + length > tmp_space_size)
3532 	{
3533 	  /* Flush buffer before refilling or reallocating.  */
3534 	  amt = p - tmp_space;
3535 	  if (bfd_bwrite ((void *) &tmp_space[0], amt, abfd) != amt)
3536 	    return FALSE;
3537 
3538 	  /* Reallocate if now empty buffer still too small.  */
3539 	  if (5 + length > tmp_space_size)
3540 	    {
3541 	      /* See alloca above for discussion of new size.  */
3542 	      if (2 * tmp_space_size < 5 + length)
3543 		tmp_space_size = 5 + length;
3544 	      else
3545 		tmp_space_size = 2 * tmp_space_size;
3546 	      tmp_space = xrealloc (tmp_space, tmp_space_size);
3547 	    }
3548 
3549 	  /* Reset to beginning of the (possibly new) buffer space.  */
3550 	  p = tmp_space;
3551 	}
3552 
3553       /* First element in a string table entry is the length of the
3554 	 string.  This must always be 4 byte aligned.  This is also
3555 	 an appropriate time to fill in the string index field in the
3556 	 symbol table entry.  */
3557       bfd_put_32 (abfd, (bfd_vma) length, p);
3558       strings_size += 4;
3559       p += 4;
3560 
3561       /* Next comes the string itself + a null terminator.  */
3562       strcpy (p, syms[i]->name);
3563 
3564       som_symbol_data (syms[i])->stringtab_offset = strings_size;
3565       p += length + 1;
3566       strings_size += length + 1;
3567 
3568       /* Always align up to the next word boundary.  */
3569       while (strings_size % 4)
3570 	{
3571 	  bfd_put_8 (abfd, 0, p);
3572 	  strings_size++;
3573 	  p++;
3574 	}
3575     }
3576 
3577   /* Scribble out any partial block.  */
3578   amt = p - tmp_space;
3579   res = bfd_bwrite ((void *) &tmp_space[0], amt, abfd);
3580   free (tmp_space);
3581   if (res != amt)
3582     return FALSE;
3583 
3584   *string_sizep = strings_size;
3585   return TRUE;
3586 }
3587 
3588 /* Compute variable information to be placed in the SOM headers,
3589    space/subspace dictionaries, relocation streams, etc.  Begin
3590    writing parts of the object file.  */
3591 
3592 static bfd_boolean
3593 som_begin_writing (bfd *abfd)
3594 {
3595   unsigned long current_offset = 0;
3596   unsigned int strings_size = 0;
3597   unsigned long num_spaces, num_subspaces, i;
3598   asection *section;
3599   unsigned int total_subspaces = 0;
3600   struct som_exec_auxhdr *exec_header = NULL;
3601 
3602   /* The file header will always be first in an object file,
3603      everything else can be in random locations.  To keep things
3604      "simple" BFD will lay out the object file in the manner suggested
3605      by the PRO ABI for PA-RISC Systems.  */
3606 
3607   /* Before any output can really begin offsets for all the major
3608      portions of the object file must be computed.  So, starting
3609      with the initial file header compute (and sometimes write)
3610      each portion of the object file.  */
3611 
3612   /* Make room for the file header, it's contents are not complete
3613      yet, so it can not be written at this time.  */
3614   current_offset += sizeof (struct som_external_header);
3615 
3616   /* Any auxiliary headers will follow the file header.  Right now
3617      we support only the copyright and version headers.  */
3618   obj_som_file_hdr (abfd)->aux_header_location = current_offset;
3619   obj_som_file_hdr (abfd)->aux_header_size = 0;
3620   if (abfd->flags & (EXEC_P | DYNAMIC))
3621     {
3622       /* Parts of the exec header will be filled in later, so
3623 	 delay writing the header itself.  Fill in the defaults,
3624 	 and write it later.  */
3625       current_offset += sizeof (struct som_external_exec_auxhdr);
3626       obj_som_file_hdr (abfd)->aux_header_size
3627 	+= sizeof (struct som_external_exec_auxhdr);
3628       exec_header = obj_som_exec_hdr (abfd);
3629       exec_header->som_auxhdr.type = EXEC_AUX_ID;
3630       exec_header->som_auxhdr.length = 40;
3631     }
3632   if (obj_som_version_hdr (abfd) != NULL)
3633     {
3634       struct som_external_string_auxhdr ext_string_auxhdr;
3635       bfd_size_type len;
3636 
3637       if (bfd_seek (abfd, (file_ptr) current_offset, SEEK_SET) != 0)
3638 	return FALSE;
3639 
3640       /* Write the aux_id structure and the string length.  */
3641       len = sizeof (struct som_external_string_auxhdr);
3642       obj_som_file_hdr (abfd)->aux_header_size += len;
3643       current_offset += len;
3644       som_swap_string_auxhdr_out
3645 	(obj_som_version_hdr (abfd), &ext_string_auxhdr);
3646       if (bfd_bwrite (&ext_string_auxhdr, len, abfd) != len)
3647 	return FALSE;
3648 
3649       /* Write the version string.  */
3650       len = obj_som_version_hdr (abfd)->header_id.length - 4;
3651       obj_som_file_hdr (abfd)->aux_header_size += len;
3652       current_offset += len;
3653       if (bfd_bwrite ((void *) obj_som_version_hdr (abfd)->string, len, abfd)
3654 	  != len)
3655 	return FALSE;
3656     }
3657 
3658   if (obj_som_copyright_hdr (abfd) != NULL)
3659     {
3660       struct som_external_string_auxhdr ext_string_auxhdr;
3661       bfd_size_type len;
3662 
3663       if (bfd_seek (abfd, (file_ptr) current_offset, SEEK_SET) != 0)
3664 	return FALSE;
3665 
3666       /* Write the aux_id structure and the string length.  */
3667       len = sizeof (struct som_external_string_auxhdr);
3668       obj_som_file_hdr (abfd)->aux_header_size += len;
3669       current_offset += len;
3670       som_swap_string_auxhdr_out
3671 	(obj_som_copyright_hdr (abfd), &ext_string_auxhdr);
3672       if (bfd_bwrite (&ext_string_auxhdr, len, abfd) != len)
3673 	return FALSE;
3674 
3675       /* Write the copyright string.  */
3676       len = obj_som_copyright_hdr (abfd)->header_id.length - 4;
3677       obj_som_file_hdr (abfd)->aux_header_size += len;
3678       current_offset += len;
3679       if (bfd_bwrite ((void *) obj_som_copyright_hdr (abfd)->string, len, abfd)
3680 	  != len)
3681 	return FALSE;
3682     }
3683 
3684   /* Next comes the initialization pointers; we have no initialization
3685      pointers, so current offset does not change.  */
3686   obj_som_file_hdr (abfd)->init_array_location = current_offset;
3687   obj_som_file_hdr (abfd)->init_array_total = 0;
3688 
3689   /* Next are the space records.  These are fixed length records.
3690 
3691      Count the number of spaces to determine how much room is needed
3692      in the object file for the space records.
3693 
3694      The names of the spaces are stored in a separate string table,
3695      and the index for each space into the string table is computed
3696      below.  Therefore, it is not possible to write the space headers
3697      at this time.  */
3698   num_spaces = som_count_spaces (abfd);
3699   obj_som_file_hdr (abfd)->space_location = current_offset;
3700   obj_som_file_hdr (abfd)->space_total = num_spaces;
3701   current_offset +=
3702     num_spaces * sizeof (struct som_external_space_dictionary_record);
3703 
3704   /* Next are the subspace records.  These are fixed length records.
3705 
3706      Count the number of subspaes to determine how much room is needed
3707      in the object file for the subspace records.
3708 
3709      A variety if fields in the subspace record are still unknown at
3710      this time (index into string table, fixup stream location/size, etc).  */
3711   num_subspaces = som_count_subspaces (abfd);
3712   obj_som_file_hdr (abfd)->subspace_location = current_offset;
3713   obj_som_file_hdr (abfd)->subspace_total = num_subspaces;
3714   current_offset
3715     += num_subspaces * sizeof (struct som_external_subspace_dictionary_record);
3716 
3717   /* Next is the string table for the space/subspace names.  We will
3718      build and write the string table on the fly.  At the same time
3719      we will fill in the space/subspace name index fields.  */
3720 
3721   /* The string table needs to be aligned on a word boundary.  */
3722   if (current_offset % 4)
3723     current_offset += (4 - (current_offset % 4));
3724 
3725   /* Mark the offset of the space/subspace string table in the
3726      file header.  */
3727   obj_som_file_hdr (abfd)->space_strings_location = current_offset;
3728 
3729   /* Scribble out the space strings.  */
3730   if (! som_write_space_strings (abfd, current_offset, &strings_size))
3731     return FALSE;
3732 
3733   /* Record total string table size in the header and update the
3734      current offset.  */
3735   obj_som_file_hdr (abfd)->space_strings_size = strings_size;
3736   current_offset += strings_size;
3737 
3738   /* Next is the compilation unit.  */
3739   obj_som_file_hdr (abfd)->compiler_location = current_offset;
3740   obj_som_file_hdr (abfd)->compiler_total = 0;
3741   if (obj_som_compilation_unit (abfd))
3742     {
3743       obj_som_file_hdr (abfd)->compiler_total = 1;
3744       current_offset += sizeof (struct som_external_compilation_unit);
3745     }
3746 
3747   /* Now compute the file positions for the loadable subspaces, taking
3748      care to make sure everything stays properly aligned.  */
3749 
3750   section = abfd->sections;
3751   for (i = 0; i < num_spaces; i++)
3752     {
3753       asection *subsection;
3754       int first_subspace;
3755       unsigned int subspace_offset = 0;
3756 
3757       /* Find a space.  */
3758       while (!som_is_space (section))
3759 	section = section->next;
3760 
3761       first_subspace = 1;
3762       /* Now look for all its subspaces.  */
3763       for (subsection = abfd->sections;
3764 	   subsection != NULL;
3765 	   subsection = subsection->next)
3766 	{
3767 
3768 	  if (!som_is_subspace (subsection)
3769 	      || !som_is_container (section, subsection)
3770 	      || (subsection->flags & SEC_ALLOC) == 0)
3771 	    continue;
3772 
3773 	  /* If this is the first subspace in the space, and we are
3774 	     building an executable, then take care to make sure all
3775 	     the alignments are correct and update the exec header.  */
3776 	  if (first_subspace
3777 	      && (abfd->flags & (EXEC_P | DYNAMIC)))
3778 	    {
3779 	      /* Demand paged executables have each space aligned to a
3780 		 page boundary.  Sharable executables (write-protected
3781 		 text) have just the private (aka data & bss) space aligned
3782 		 to a page boundary.  Ugh.  Not true for HPUX.
3783 
3784 		 The HPUX kernel requires the text to always be page aligned
3785 		 within the file regardless of the executable's type.  */
3786 	      if (abfd->flags & (D_PAGED | DYNAMIC)
3787 		  || (subsection->flags & SEC_CODE)
3788 		  || ((abfd->flags & WP_TEXT)
3789 		      && (subsection->flags & SEC_DATA)))
3790 		current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
3791 
3792 	      /* Update the exec header.  */
3793 	      if (subsection->flags & SEC_CODE && exec_header->exec_tfile == 0)
3794 		{
3795 		  exec_header->exec_tmem = section->vma;
3796 		  exec_header->exec_tfile = current_offset;
3797 		}
3798 	      if (subsection->flags & SEC_DATA && exec_header->exec_dfile == 0)
3799 		{
3800 		  exec_header->exec_dmem = section->vma;
3801 		  exec_header->exec_dfile = current_offset;
3802 		}
3803 
3804 	      /* Keep track of exactly where we are within a particular
3805 		 space.  This is necessary as the braindamaged HPUX
3806 		 loader will create holes between subspaces *and*
3807 		 subspace alignments are *NOT* preserved.  What a crock.  */
3808 	      subspace_offset = subsection->vma;
3809 
3810 	      /* Only do this for the first subspace within each space.  */
3811 	      first_subspace = 0;
3812 	    }
3813 	  else if (abfd->flags & (EXEC_P | DYNAMIC))
3814 	    {
3815 	      /* The braindamaged HPUX loader may have created a hole
3816 		 between two subspaces.  It is *not* sufficient to use
3817 		 the alignment specifications within the subspaces to
3818 		 account for these holes -- I've run into at least one
3819 		 case where the loader left one code subspace unaligned
3820 		 in a final executable.
3821 
3822 		 To combat this we keep a current offset within each space,
3823 		 and use the subspace vma fields to detect and preserve
3824 		 holes.  What a crock!
3825 
3826 		 ps.  This is not necessary for unloadable space/subspaces.  */
3827 	      current_offset += subsection->vma - subspace_offset;
3828 	      if (subsection->flags & SEC_CODE)
3829 		exec_header->exec_tsize += subsection->vma - subspace_offset;
3830 	      else
3831 		exec_header->exec_dsize += subsection->vma - subspace_offset;
3832 	      subspace_offset += subsection->vma - subspace_offset;
3833 	    }
3834 
3835 	  subsection->target_index = total_subspaces++;
3836 	  /* This is real data to be loaded from the file.  */
3837 	  if (subsection->flags & SEC_LOAD)
3838 	    {
3839 	      /* Update the size of the code & data.  */
3840 	      if (abfd->flags & (EXEC_P | DYNAMIC)
3841 		  && subsection->flags & SEC_CODE)
3842 		exec_header->exec_tsize += subsection->size;
3843 	      else if (abfd->flags & (EXEC_P | DYNAMIC)
3844 		       && subsection->flags & SEC_DATA)
3845 		exec_header->exec_dsize += subsection->size;
3846 	      som_section_data (subsection)->subspace_dict->file_loc_init_value
3847 		= current_offset;
3848 	      subsection->filepos = current_offset;
3849 	      current_offset += subsection->size;
3850 	      subspace_offset += subsection->size;
3851 	    }
3852 	  /* Looks like uninitialized data.  */
3853 	  else
3854 	    {
3855 	      /* Update the size of the bss section.  */
3856 	      if (abfd->flags & (EXEC_P | DYNAMIC))
3857 		exec_header->exec_bsize += subsection->size;
3858 
3859 	      som_section_data (subsection)->subspace_dict->file_loc_init_value
3860 		= 0;
3861 	      som_section_data (subsection)->subspace_dict->
3862 		initialization_length = 0;
3863 	    }
3864 	}
3865       /* Goto the next section.  */
3866       section = section->next;
3867     }
3868 
3869   /* Finally compute the file positions for unloadable subspaces.
3870      If building an executable, start the unloadable stuff on its
3871      own page.  */
3872 
3873   if (abfd->flags & (EXEC_P | DYNAMIC))
3874     current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
3875 
3876   obj_som_file_hdr (abfd)->unloadable_sp_location = current_offset;
3877   section = abfd->sections;
3878   for (i = 0; i < num_spaces; i++)
3879     {
3880       asection *subsection;
3881 
3882       /* Find a space.  */
3883       while (!som_is_space (section))
3884 	section = section->next;
3885 
3886       if (abfd->flags & (EXEC_P | DYNAMIC))
3887 	current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
3888 
3889       /* Now look for all its subspaces.  */
3890       for (subsection = abfd->sections;
3891 	   subsection != NULL;
3892 	   subsection = subsection->next)
3893 	{
3894 
3895 	  if (!som_is_subspace (subsection)
3896 	      || !som_is_container (section, subsection)
3897 	      || (subsection->flags & SEC_ALLOC) != 0)
3898 	    continue;
3899 
3900 	  subsection->target_index = total_subspaces++;
3901 	  /* This is real data to be loaded from the file.  */
3902 	  if ((subsection->flags & SEC_LOAD) == 0)
3903 	    {
3904 	      som_section_data (subsection)->subspace_dict->file_loc_init_value
3905 		= current_offset;
3906 	      subsection->filepos = current_offset;
3907 	      current_offset += subsection->size;
3908 	    }
3909 	  /* Looks like uninitialized data.  */
3910 	  else
3911 	    {
3912 	      som_section_data (subsection)->subspace_dict->file_loc_init_value
3913 		= 0;
3914 	      som_section_data (subsection)->subspace_dict->
3915 		initialization_length = subsection->size;
3916 	    }
3917 	}
3918       /* Goto the next section.  */
3919       section = section->next;
3920     }
3921 
3922   /* If building an executable, then make sure to seek to and write
3923      one byte at the end of the file to make sure any necessary
3924      zeros are filled in.  Ugh.  */
3925   if (abfd->flags & (EXEC_P | DYNAMIC))
3926     current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
3927   if (bfd_seek (abfd, (file_ptr) current_offset - 1, SEEK_SET) != 0)
3928     return FALSE;
3929   if (bfd_bwrite ((void *) "", (bfd_size_type) 1, abfd) != 1)
3930     return FALSE;
3931 
3932   obj_som_file_hdr (abfd)->unloadable_sp_size
3933     = current_offset - obj_som_file_hdr (abfd)->unloadable_sp_location;
3934 
3935   /* Loader fixups are not supported in any way shape or form.  */
3936   obj_som_file_hdr (abfd)->loader_fixup_location = 0;
3937   obj_som_file_hdr (abfd)->loader_fixup_total = 0;
3938 
3939   /* Done.  Store the total size of the SOM so far.  */
3940   obj_som_file_hdr (abfd)->som_length = current_offset;
3941 
3942   return TRUE;
3943 }
3944 
3945 /* Finally, scribble out the various headers to the disk.  */
3946 
3947 static bfd_boolean
3948 som_finish_writing (bfd *abfd)
3949 {
3950   int num_spaces = som_count_spaces (abfd);
3951   asymbol **syms = bfd_get_outsymbols (abfd);
3952   int i, num_syms;
3953   int subspace_index = 0;
3954   file_ptr location;
3955   asection *section;
3956   unsigned long current_offset;
3957   unsigned int strings_size, total_reloc_size;
3958   bfd_size_type amt;
3959   struct som_external_header ext_header;
3960 
3961   /* We must set up the version identifier here as objcopy/strip copy
3962      private BFD data too late for us to handle this in som_begin_writing.  */
3963   if (obj_som_exec_data (abfd)
3964       && obj_som_exec_data (abfd)->version_id)
3965     obj_som_file_hdr (abfd)->version_id = obj_som_exec_data (abfd)->version_id;
3966   else
3967     obj_som_file_hdr (abfd)->version_id = NEW_VERSION_ID;
3968 
3969   /* Next is the symbol table.  These are fixed length records.
3970 
3971      Count the number of symbols to determine how much room is needed
3972      in the object file for the symbol table.
3973 
3974      The names of the symbols are stored in a separate string table,
3975      and the index for each symbol name into the string table is computed
3976      below.  Therefore, it is not possible to write the symbol table
3977      at this time.
3978 
3979      These used to be output before the subspace contents, but they
3980      were moved here to work around a stupid bug in the hpux linker
3981      (fixed in hpux10).  */
3982   current_offset = obj_som_file_hdr (abfd)->som_length;
3983 
3984   /* Make sure we're on a word boundary.  */
3985   if (current_offset % 4)
3986     current_offset += (4 - (current_offset % 4));
3987 
3988   num_syms = bfd_get_symcount (abfd);
3989   obj_som_file_hdr (abfd)->symbol_location = current_offset;
3990   obj_som_file_hdr (abfd)->symbol_total = num_syms;
3991   current_offset +=
3992     num_syms * sizeof (struct som_external_symbol_dictionary_record);
3993 
3994   /* Next are the symbol strings.
3995      Align them to a word boundary.  */
3996   if (current_offset % 4)
3997     current_offset += (4 - (current_offset % 4));
3998   obj_som_file_hdr (abfd)->symbol_strings_location = current_offset;
3999 
4000   /* Scribble out the symbol strings.  */
4001   if (! som_write_symbol_strings (abfd, current_offset, syms,
4002 				  num_syms, &strings_size,
4003 				  obj_som_compilation_unit (abfd)))
4004     return FALSE;
4005 
4006   /* Record total string table size in header and update the
4007      current offset.  */
4008   obj_som_file_hdr (abfd)->symbol_strings_size = strings_size;
4009   current_offset += strings_size;
4010 
4011   /* Do prep work before handling fixups.  */
4012   som_prep_for_fixups (abfd,
4013 		       bfd_get_outsymbols (abfd),
4014 		       bfd_get_symcount (abfd));
4015 
4016   /* At the end of the file is the fixup stream which starts on a
4017      word boundary.  */
4018   if (current_offset % 4)
4019     current_offset += (4 - (current_offset % 4));
4020   obj_som_file_hdr (abfd)->fixup_request_location = current_offset;
4021 
4022   /* Write the fixups and update fields in subspace headers which
4023      relate to the fixup stream.  */
4024   if (! som_write_fixups (abfd, current_offset, &total_reloc_size))
4025     return FALSE;
4026 
4027   /* Record the total size of the fixup stream in the file header.  */
4028   obj_som_file_hdr (abfd)->fixup_request_total = total_reloc_size;
4029 
4030   /* Done.  Store the total size of the SOM.  */
4031   obj_som_file_hdr (abfd)->som_length = current_offset + total_reloc_size;
4032 
4033   /* Now that the symbol table information is complete, build and
4034      write the symbol table.  */
4035   if (! som_build_and_write_symbol_table (abfd))
4036     return FALSE;
4037 
4038   /* Subspaces are written first so that we can set up information
4039      about them in their containing spaces as the subspace is written.  */
4040 
4041   /* Seek to the start of the subspace dictionary records.  */
4042   location = obj_som_file_hdr (abfd)->subspace_location;
4043   if (bfd_seek (abfd, location, SEEK_SET) != 0)
4044     return FALSE;
4045 
4046   section = abfd->sections;
4047   /* Now for each loadable space write out records for its subspaces.  */
4048   for (i = 0; i < num_spaces; i++)
4049     {
4050       asection *subsection;
4051 
4052       /* Find a space.  */
4053       while (!som_is_space (section))
4054 	section = section->next;
4055 
4056       /* Now look for all its subspaces.  */
4057       for (subsection = abfd->sections;
4058 	   subsection != NULL;
4059 	   subsection = subsection->next)
4060 	{
4061 	  struct som_external_subspace_dictionary_record ext_subspace_dict;
4062 
4063 	  /* Skip any section which does not correspond to a space
4064 	     or subspace.  Or does not have SEC_ALLOC set (and therefore
4065 	     has no real bits on the disk).  */
4066 	  if (!som_is_subspace (subsection)
4067 	      || !som_is_container (section, subsection)
4068 	      || (subsection->flags & SEC_ALLOC) == 0)
4069 	    continue;
4070 
4071 	  /* If this is the first subspace for this space, then save
4072 	     the index of the subspace in its containing space.  Also
4073 	     set "is_loadable" in the containing space.  */
4074 
4075 	  if (som_section_data (section)->space_dict->subspace_quantity == 0)
4076 	    {
4077 	      som_section_data (section)->space_dict->is_loadable = 1;
4078 	      som_section_data (section)->space_dict->subspace_index
4079 		= subspace_index;
4080 	    }
4081 
4082 	  /* Increment the number of subspaces seen and the number of
4083 	     subspaces contained within the current space.  */
4084 	  subspace_index++;
4085 	  som_section_data (section)->space_dict->subspace_quantity++;
4086 
4087 	  /* Mark the index of the current space within the subspace's
4088 	     dictionary record.  */
4089 	  som_section_data (subsection)->subspace_dict->space_index = i;
4090 
4091 	  /* Dump the current subspace header.  */
4092 	  som_swap_subspace_dictionary_record_out
4093 	    (som_section_data (subsection)->subspace_dict, &ext_subspace_dict);
4094 	  amt = sizeof (struct som_subspace_dictionary_record);
4095 	  if (bfd_bwrite (&ext_subspace_dict, amt, abfd) != amt)
4096 	    return FALSE;
4097 	}
4098       /* Goto the next section.  */
4099       section = section->next;
4100     }
4101 
4102   /* Now repeat the process for unloadable subspaces.  */
4103   section = abfd->sections;
4104   /* Now for each space write out records for its subspaces.  */
4105   for (i = 0; i < num_spaces; i++)
4106     {
4107       asection *subsection;
4108 
4109       /* Find a space.  */
4110       while (!som_is_space (section))
4111 	section = section->next;
4112 
4113       /* Now look for all its subspaces.  */
4114       for (subsection = abfd->sections;
4115 	   subsection != NULL;
4116 	   subsection = subsection->next)
4117 	{
4118 	  struct som_external_subspace_dictionary_record ext_subspace_dict;
4119 
4120 	  /* Skip any section which does not correspond to a space or
4121 	     subspace, or which SEC_ALLOC set (and therefore handled
4122 	     in the loadable spaces/subspaces code above).  */
4123 
4124 	  if (!som_is_subspace (subsection)
4125 	      || !som_is_container (section, subsection)
4126 	      || (subsection->flags & SEC_ALLOC) != 0)
4127 	    continue;
4128 
4129 	  /* If this is the first subspace for this space, then save
4130 	     the index of the subspace in its containing space.  Clear
4131 	     "is_loadable".  */
4132 
4133 	  if (som_section_data (section)->space_dict->subspace_quantity == 0)
4134 	    {
4135 	      som_section_data (section)->space_dict->is_loadable = 0;
4136 	      som_section_data (section)->space_dict->subspace_index
4137 		= subspace_index;
4138 	    }
4139 
4140 	  /* Increment the number of subspaces seen and the number of
4141 	     subspaces contained within the current space.  */
4142 	  som_section_data (section)->space_dict->subspace_quantity++;
4143 	  subspace_index++;
4144 
4145 	  /* Mark the index of the current space within the subspace's
4146 	     dictionary record.  */
4147 	  som_section_data (subsection)->subspace_dict->space_index = i;
4148 
4149 	  /* Dump this subspace header.  */
4150 	  som_swap_subspace_dictionary_record_out
4151 	    (som_section_data (subsection)->subspace_dict, &ext_subspace_dict);
4152 	  amt = sizeof (struct som_subspace_dictionary_record);
4153 	  if (bfd_bwrite (&ext_subspace_dict, amt, abfd) != amt)
4154 	    return FALSE;
4155 	}
4156       /* Goto the next section.  */
4157       section = section->next;
4158     }
4159 
4160   /* All the subspace dictionary records are written, and all the
4161      fields are set up in the space dictionary records.
4162 
4163      Seek to the right location and start writing the space
4164      dictionary records.  */
4165   location = obj_som_file_hdr (abfd)->space_location;
4166   if (bfd_seek (abfd, location, SEEK_SET) != 0)
4167     return FALSE;
4168 
4169   section = abfd->sections;
4170   for (i = 0; i < num_spaces; i++)
4171     {
4172       struct som_external_space_dictionary_record ext_space_dict;
4173 
4174       /* Find a space.  */
4175       while (!som_is_space (section))
4176 	section = section->next;
4177 
4178       /* Dump its header.  */
4179       som_swap_space_dictionary_out (som_section_data (section)->space_dict,
4180 				     &ext_space_dict);
4181       amt = sizeof (struct som_external_space_dictionary_record);
4182       if (bfd_bwrite (&ext_space_dict, amt, abfd) != amt)
4183 	return FALSE;
4184 
4185       /* Goto the next section.  */
4186       section = section->next;
4187     }
4188 
4189   /* Write the compilation unit record if there is one.  */
4190   if (obj_som_compilation_unit (abfd))
4191     {
4192       struct som_external_compilation_unit ext_comp_unit;
4193 
4194       location = obj_som_file_hdr (abfd)->compiler_location;
4195       if (bfd_seek (abfd, location, SEEK_SET) != 0)
4196 	return FALSE;
4197 
4198       som_swap_compilation_unit_out
4199 	(obj_som_compilation_unit (abfd), &ext_comp_unit);
4200 
4201       amt = sizeof (struct som_external_compilation_unit);
4202       if (bfd_bwrite (&ext_comp_unit, amt, abfd) != amt)
4203 	return FALSE;
4204     }
4205 
4206   /* Setting of the system_id has to happen very late now that copying of
4207      BFD private data happens *after* section contents are set.  */
4208   if (abfd->flags & (EXEC_P | DYNAMIC))
4209     obj_som_file_hdr (abfd)->system_id = obj_som_exec_data (abfd)->system_id;
4210   else if (bfd_get_mach (abfd) == pa20)
4211     obj_som_file_hdr (abfd)->system_id = CPU_PA_RISC2_0;
4212   else if (bfd_get_mach (abfd) == pa11)
4213     obj_som_file_hdr (abfd)->system_id = CPU_PA_RISC1_1;
4214   else
4215     obj_som_file_hdr (abfd)->system_id = CPU_PA_RISC1_0;
4216 
4217   /* Swap and compute the checksum for the file header just before writing
4218      the header to disk.  */
4219   som_swap_header_out (obj_som_file_hdr (abfd), &ext_header);
4220   bfd_putb32 (som_compute_checksum (&ext_header), ext_header.checksum);
4221 
4222   /* Only thing left to do is write out the file header.  It is always
4223      at location zero.  Seek there and write it.  */
4224   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
4225     return FALSE;
4226   amt = sizeof (struct som_external_header);
4227   if (bfd_bwrite (&ext_header, amt, abfd) != amt)
4228     return FALSE;
4229 
4230   /* Now write the exec header.  */
4231   if (abfd->flags & (EXEC_P | DYNAMIC))
4232     {
4233       long tmp, som_length;
4234       struct som_exec_auxhdr *exec_header;
4235       struct som_external_exec_auxhdr ext_exec_header;
4236 
4237       exec_header = obj_som_exec_hdr (abfd);
4238       exec_header->exec_entry = bfd_get_start_address (abfd);
4239       exec_header->exec_flags = obj_som_exec_data (abfd)->exec_flags;
4240 
4241       /* Oh joys.  Ram some of the BSS data into the DATA section
4242 	 to be compatible with how the hp linker makes objects
4243 	 (saves memory space).  */
4244       tmp = exec_header->exec_dsize;
4245       tmp = SOM_ALIGN (tmp, PA_PAGESIZE);
4246       exec_header->exec_bsize -= (tmp - exec_header->exec_dsize);
4247       if (exec_header->exec_bsize < 0)
4248 	exec_header->exec_bsize = 0;
4249       exec_header->exec_dsize = tmp;
4250 
4251       /* Now perform some sanity checks.  The idea is to catch bogons now and
4252 	 inform the user, instead of silently generating a bogus file.  */
4253       som_length = obj_som_file_hdr (abfd)->som_length;
4254       if (exec_header->exec_tfile + exec_header->exec_tsize > som_length
4255 	  || exec_header->exec_dfile + exec_header->exec_dsize > som_length)
4256 	{
4257 	  bfd_set_error (bfd_error_bad_value);
4258 	  return FALSE;
4259 	}
4260 
4261       som_swap_exec_auxhdr_out (exec_header, &ext_exec_header);
4262 
4263       if (bfd_seek (abfd, obj_som_file_hdr (abfd)->aux_header_location,
4264 		    SEEK_SET) != 0)
4265 	return FALSE;
4266 
4267       amt = sizeof (ext_exec_header);
4268       if (bfd_bwrite (&ext_exec_header, amt, abfd) != amt)
4269 	return FALSE;
4270     }
4271   return TRUE;
4272 }
4273 
4274 /* Compute and return the checksum for a SOM file header.  */
4275 
4276 static unsigned long
4277 som_compute_checksum (struct som_external_header *hdr)
4278 {
4279   unsigned long checksum, count, i;
4280   unsigned long *buffer = (unsigned long *) hdr;
4281 
4282   checksum = 0;
4283   count = sizeof (struct som_external_header) / 4;
4284   for (i = 0; i < count; i++)
4285     checksum ^= *(buffer + i);
4286 
4287   return checksum;
4288 }
4289 
4290 static void
4291 som_bfd_derive_misc_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
4292 				 asymbol *sym,
4293 				 struct som_misc_symbol_info *info)
4294 {
4295   /* Initialize.  */
4296   memset (info, 0, sizeof (struct som_misc_symbol_info));
4297 
4298   /* The HP SOM linker requires detailed type information about
4299      all symbols (including undefined symbols!).  Unfortunately,
4300      the type specified in an import/export statement does not
4301      always match what the linker wants.  Severe braindamage.  */
4302 
4303   /* Section symbols will not have a SOM symbol type assigned to
4304      them yet.  Assign all section symbols type ST_DATA.  */
4305   if (sym->flags & BSF_SECTION_SYM)
4306     info->symbol_type = ST_DATA;
4307   else
4308     {
4309       /* For BFD style common, the linker will choke unless we set the
4310 	 type and scope to ST_STORAGE and SS_UNSAT, respectively.  */
4311       if (bfd_is_com_section (sym->section))
4312 	{
4313 	  info->symbol_type = ST_STORAGE;
4314 	  info->symbol_scope = SS_UNSAT;
4315 	}
4316 
4317       /* It is possible to have a symbol without an associated
4318 	 type.  This happens if the user imported the symbol
4319 	 without a type and the symbol was never defined
4320 	 locally.  If BSF_FUNCTION is set for this symbol, then
4321 	 assign it type ST_CODE (the HP linker requires undefined
4322 	 external functions to have type ST_CODE rather than ST_ENTRY).  */
4323       else if ((som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN
4324 		|| som_symbol_data (sym)->som_type == SYMBOL_TYPE_CODE)
4325 	       && bfd_is_und_section (sym->section)
4326 	       && sym->flags & BSF_FUNCTION)
4327 	info->symbol_type = ST_CODE;
4328 
4329       /* Handle function symbols which were defined in this file.
4330 	 They should have type ST_ENTRY.  Also retrieve the argument
4331 	 relocation bits from the SOM backend information.  */
4332       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_ENTRY
4333 	       || (som_symbol_data (sym)->som_type == SYMBOL_TYPE_CODE
4334 		   && (sym->flags & BSF_FUNCTION))
4335 	       || (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN
4336 		   && (sym->flags & BSF_FUNCTION)))
4337 	{
4338 	  info->symbol_type = ST_ENTRY;
4339 	  info->arg_reloc = som_symbol_data (sym)->tc_data.ap.hppa_arg_reloc;
4340 	  info->priv_level= som_symbol_data (sym)->tc_data.ap.hppa_priv_level;
4341 	}
4342 
4343       /* For unknown symbols set the symbol's type based on the symbol's
4344 	 section (ST_DATA for DATA sections, ST_CODE for CODE sections).  */
4345       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN)
4346 	{
4347 	  if (bfd_is_abs_section (sym->section))
4348 	    info->symbol_type = ST_ABSOLUTE;
4349 	  else if (sym->section->flags & SEC_CODE)
4350 	    info->symbol_type = ST_CODE;
4351 	  else
4352 	    info->symbol_type = ST_DATA;
4353 	}
4354 
4355       /* From now on it's a very simple mapping.  */
4356       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_ABSOLUTE)
4357 	info->symbol_type = ST_ABSOLUTE;
4358       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_CODE)
4359 	info->symbol_type = ST_CODE;
4360       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_DATA)
4361 	info->symbol_type = ST_DATA;
4362       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_MILLICODE)
4363 	info->symbol_type = ST_MILLICODE;
4364       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_PLABEL)
4365 	info->symbol_type = ST_PLABEL;
4366       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_PRI_PROG)
4367 	info->symbol_type = ST_PRI_PROG;
4368       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_SEC_PROG)
4369 	info->symbol_type = ST_SEC_PROG;
4370     }
4371 
4372   /* Now handle the symbol's scope.  Exported data which is not
4373      in the common section has scope SS_UNIVERSAL.  Note scope
4374      of common symbols was handled earlier!  */
4375   if (bfd_is_com_section (sym->section))
4376     ;
4377   else if (bfd_is_und_section (sym->section))
4378     info->symbol_scope = SS_UNSAT;
4379   else if (sym->flags & (BSF_EXPORT | BSF_WEAK))
4380     info->symbol_scope = SS_UNIVERSAL;
4381   /* Anything else which is not in the common section has scope
4382      SS_LOCAL.  */
4383   else
4384     info->symbol_scope = SS_LOCAL;
4385 
4386   /* Now set the symbol_info field.  It has no real meaning
4387      for undefined or common symbols, but the HP linker will
4388      choke if it's not set to some "reasonable" value.  We
4389      use zero as a reasonable value.  */
4390   if (bfd_is_com_section (sym->section)
4391       || bfd_is_und_section (sym->section)
4392       || bfd_is_abs_section (sym->section))
4393     info->symbol_info = 0;
4394   /* For all other symbols, the symbol_info field contains the
4395      subspace index of the space this symbol is contained in.  */
4396   else
4397     info->symbol_info = sym->section->target_index;
4398 
4399   /* Set the symbol's value.  */
4400   info->symbol_value = sym->value + sym->section->vma;
4401 
4402   /* The secondary_def field is for "weak" symbols.  */
4403   if (sym->flags & BSF_WEAK)
4404     info->secondary_def = TRUE;
4405   else
4406     info->secondary_def = FALSE;
4407 
4408   /* The is_comdat, is_common and dup_common fields provide various
4409      flavors of common.
4410 
4411      For data symbols, setting IS_COMMON provides Fortran style common
4412      (duplicate definitions and overlapped initialization).  Setting both
4413      IS_COMMON and DUP_COMMON provides Cobol style common (duplicate
4414      definitions as long as they are all the same length).  In a shared
4415      link data symbols retain their IS_COMMON and DUP_COMMON flags.
4416      An IS_COMDAT data symbol is similar to a IS_COMMON | DUP_COMMON
4417      symbol except in that it loses its IS_COMDAT flag in a shared link.
4418 
4419      For code symbols, IS_COMDAT and DUP_COMMON have effect.  Universal
4420      DUP_COMMON code symbols are not exported from shared libraries.
4421      IS_COMDAT symbols are exported but they lose their IS_COMDAT flag.
4422 
4423      We take a simplified approach to setting the is_comdat, is_common
4424      and dup_common flags in symbols based on the flag settings of their
4425      subspace.  This avoids having to add directives like `.comdat' but
4426      the linker behavior is probably undefined if there is more than one
4427      universal symbol (comdat key sysmbol) in a subspace.
4428 
4429      The behavior of these flags is not well documentmented, so there
4430      may be bugs and some surprising interactions with other flags.  */
4431   if (som_section_data (sym->section)
4432       && som_section_data (sym->section)->subspace_dict
4433       && info->symbol_scope == SS_UNIVERSAL
4434       && (info->symbol_type == ST_ENTRY
4435 	  || info->symbol_type == ST_CODE
4436 	  || info->symbol_type == ST_DATA))
4437     {
4438       info->is_comdat
4439 	= som_section_data (sym->section)->subspace_dict->is_comdat;
4440       info->is_common
4441 	= som_section_data (sym->section)->subspace_dict->is_common;
4442       info->dup_common
4443 	= som_section_data (sym->section)->subspace_dict->dup_common;
4444     }
4445 }
4446 
4447 /* Build and write, in one big chunk, the entire symbol table for
4448    this BFD.  */
4449 
4450 static bfd_boolean
4451 som_build_and_write_symbol_table (bfd *abfd)
4452 {
4453   unsigned int num_syms = bfd_get_symcount (abfd);
4454   file_ptr symtab_location = obj_som_file_hdr (abfd)->symbol_location;
4455   asymbol **bfd_syms = obj_som_sorted_syms (abfd);
4456   struct som_external_symbol_dictionary_record *som_symtab = NULL;
4457   unsigned int i;
4458   bfd_size_type symtab_size;
4459 
4460   /* Compute total symbol table size and allocate a chunk of memory
4461      to hold the symbol table as we build it.  */
4462   som_symtab
4463     = bfd_zmalloc2 (num_syms,
4464 		    sizeof (struct som_external_symbol_dictionary_record));
4465   if (som_symtab == NULL && num_syms != 0)
4466     goto error_return;
4467 
4468   /* Walk over each symbol.  */
4469   for (i = 0; i < num_syms; i++)
4470     {
4471       struct som_misc_symbol_info info;
4472       unsigned int flags;
4473 
4474       /* This is really an index into the symbol strings table.
4475 	 By the time we get here, the index has already been
4476 	 computed and stored into the name field in the BFD symbol.  */
4477       bfd_putb32 (som_symbol_data (bfd_syms[i])->stringtab_offset,
4478 		  som_symtab[i].name);
4479 
4480       /* Derive SOM information from the BFD symbol.  */
4481       som_bfd_derive_misc_symbol_info (abfd, bfd_syms[i], &info);
4482 
4483       /* Now use it.  */
4484       flags = (info.symbol_type << SOM_SYMBOL_TYPE_SH)
4485 	| (info.symbol_scope << SOM_SYMBOL_SCOPE_SH)
4486 	| (info.arg_reloc << SOM_SYMBOL_ARG_RELOC_SH)
4487 	| (3 << SOM_SYMBOL_XLEAST_SH)
4488 	| (info.secondary_def ? SOM_SYMBOL_SECONDARY_DEF : 0)
4489 	| (info.is_common ? SOM_SYMBOL_IS_COMMON : 0)
4490 	| (info.dup_common ? SOM_SYMBOL_DUP_COMMON : 0);
4491       bfd_putb32 (flags, som_symtab[i].flags);
4492 
4493       flags = (info.symbol_info << SOM_SYMBOL_SYMBOL_INFO_SH)
4494 	| (info.is_comdat ? SOM_SYMBOL_IS_COMDAT : 0);
4495       bfd_putb32 (flags, som_symtab[i].info);
4496       bfd_putb32 (info.symbol_value | info.priv_level,
4497 		  som_symtab[i].symbol_value);
4498     }
4499 
4500   /* Everything is ready, seek to the right location and
4501      scribble out the symbol table.  */
4502   if (bfd_seek (abfd, symtab_location, SEEK_SET) != 0)
4503     return FALSE;
4504 
4505   symtab_size = num_syms;
4506   symtab_size *= sizeof (struct som_external_symbol_dictionary_record);
4507   if (bfd_bwrite ((void *) som_symtab, symtab_size, abfd) != symtab_size)
4508     goto error_return;
4509 
4510   if (som_symtab != NULL)
4511     free (som_symtab);
4512   return TRUE;
4513  error_return:
4514   if (som_symtab != NULL)
4515     free (som_symtab);
4516   return FALSE;
4517 }
4518 
4519 /* Write an object in SOM format.  */
4520 
4521 static bfd_boolean
4522 som_write_object_contents (bfd *abfd)
4523 {
4524   if (! abfd->output_has_begun)
4525     {
4526       /* Set up fixed parts of the file, space, and subspace headers.
4527 	 Notify the world that output has begun.  */
4528       som_prep_headers (abfd);
4529       abfd->output_has_begun = TRUE;
4530       /* Start writing the object file.  This include all the string
4531 	 tables, fixup streams, and other portions of the object file.  */
4532       som_begin_writing (abfd);
4533     }
4534 
4535   return som_finish_writing (abfd);
4536 }
4537 
4538 /* Read and save the string table associated with the given BFD.  */
4539 
4540 static bfd_boolean
4541 som_slurp_string_table (bfd *abfd)
4542 {
4543   char *stringtab;
4544   bfd_size_type amt;
4545 
4546   /* Use the saved version if its available.  */
4547   if (obj_som_stringtab (abfd) != NULL)
4548     return TRUE;
4549 
4550   /* I don't think this can currently happen, and I'm not sure it should
4551      really be an error, but it's better than getting unpredictable results
4552      from the host's malloc when passed a size of zero.  */
4553   if (obj_som_stringtab_size (abfd) == 0)
4554     {
4555       bfd_set_error (bfd_error_no_symbols);
4556       return FALSE;
4557     }
4558 
4559   /* Allocate and read in the string table.  */
4560   amt = obj_som_stringtab_size (abfd);
4561   stringtab = bfd_zmalloc (amt);
4562   if (stringtab == NULL)
4563     return FALSE;
4564 
4565   if (bfd_seek (abfd, obj_som_str_filepos (abfd), SEEK_SET) != 0)
4566     return FALSE;
4567 
4568   if (bfd_bread (stringtab, amt, abfd) != amt)
4569     return FALSE;
4570 
4571   /* Save our results and return success.  */
4572   obj_som_stringtab (abfd) = stringtab;
4573   return TRUE;
4574 }
4575 
4576 /* Return the amount of data (in bytes) required to hold the symbol
4577    table for this object.  */
4578 
4579 static long
4580 som_get_symtab_upper_bound (bfd *abfd)
4581 {
4582   if (!som_slurp_symbol_table (abfd))
4583     return -1;
4584 
4585   return (bfd_get_symcount (abfd) + 1) * sizeof (asymbol *);
4586 }
4587 
4588 /* Convert from a SOM subspace index to a BFD section.  */
4589 
4590 asection *
4591 bfd_section_from_som_symbol
4592   (bfd *abfd, struct som_external_symbol_dictionary_record *symbol)
4593 {
4594   asection *section;
4595   unsigned int flags = bfd_getb32 (symbol->flags);
4596   unsigned int symbol_type = (flags >> SOM_SYMBOL_TYPE_SH) & SOM_SYMBOL_TYPE_MASK;
4597 
4598   /* The meaning of the symbol_info field changes for functions
4599      within executables.  So only use the quick symbol_info mapping for
4600      incomplete objects and non-function symbols in executables.  */
4601   if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0
4602       || (symbol_type != ST_ENTRY
4603 	  && symbol_type != ST_PRI_PROG
4604 	  && symbol_type != ST_SEC_PROG
4605 	  && symbol_type != ST_MILLICODE))
4606     {
4607       int idx = (bfd_getb32 (symbol->info) >> SOM_SYMBOL_SYMBOL_INFO_SH)
4608 	& SOM_SYMBOL_SYMBOL_INFO_MASK;
4609 
4610       for (section = abfd->sections; section != NULL; section = section->next)
4611 	if (section->target_index == idx && som_is_subspace (section))
4612 	  return section;
4613     }
4614   else
4615     {
4616       unsigned int value = bfd_getb32 (symbol->symbol_value);
4617 
4618       /* For executables we will have to use the symbol's address and
4619 	 find out what section would contain that address.   Yuk.  */
4620       for (section = abfd->sections; section; section = section->next)
4621 	if (value >= section->vma
4622 	    && value <= section->vma + section->size
4623 	    && som_is_subspace (section))
4624 	  return section;
4625     }
4626 
4627   /* Could be a symbol from an external library (such as an OMOS
4628      shared library).  Don't abort.  */
4629   return bfd_abs_section_ptr;
4630 }
4631 
4632 /* Read and save the symbol table associated with the given BFD.  */
4633 
4634 static unsigned int
4635 som_slurp_symbol_table (bfd *abfd)
4636 {
4637   int symbol_count = bfd_get_symcount (abfd);
4638   int symsize = sizeof (struct som_external_symbol_dictionary_record);
4639   char *stringtab;
4640   struct som_external_symbol_dictionary_record *buf = NULL, *bufp, *endbufp;
4641   som_symbol_type *sym, *symbase;
4642   bfd_size_type amt;
4643 
4644   /* Return saved value if it exists.  */
4645   if (obj_som_symtab (abfd) != NULL)
4646     goto successful_return;
4647 
4648   /* Special case.  This is *not* an error.  */
4649   if (symbol_count == 0)
4650     goto successful_return;
4651 
4652   if (!som_slurp_string_table (abfd))
4653     goto error_return;
4654 
4655   stringtab = obj_som_stringtab (abfd);
4656 
4657   symbase = bfd_zmalloc2 (symbol_count, sizeof (som_symbol_type));
4658   if (symbase == NULL)
4659     goto error_return;
4660 
4661   /* Read in the external SOM representation.  */
4662   buf = bfd_malloc2 (symbol_count, symsize);
4663   if (buf == NULL)
4664     goto error_return;
4665   if (bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET) != 0)
4666     goto error_return;
4667   amt = symbol_count;
4668   amt *= symsize;
4669   if (bfd_bread (buf, amt, abfd) != amt)
4670     goto error_return;
4671 
4672   /* Iterate over all the symbols and internalize them.  */
4673   endbufp = buf + symbol_count;
4674   for (bufp = buf, sym = symbase; bufp < endbufp; ++bufp)
4675     {
4676       unsigned int flags = bfd_getb32 (bufp->flags);
4677       unsigned int symbol_type =
4678 	(flags >> SOM_SYMBOL_TYPE_SH) & SOM_SYMBOL_TYPE_MASK;
4679       unsigned int symbol_scope =
4680 	(flags >> SOM_SYMBOL_SCOPE_SH) & SOM_SYMBOL_SCOPE_MASK;
4681 
4682       /* I don't think we care about these.  */
4683       if (symbol_type == ST_SYM_EXT || symbol_type == ST_ARG_EXT)
4684 	continue;
4685 
4686       /* Set some private data we care about.  */
4687       if (symbol_type == ST_NULL)
4688 	som_symbol_data (sym)->som_type = SYMBOL_TYPE_UNKNOWN;
4689       else if (symbol_type == ST_ABSOLUTE)
4690 	som_symbol_data (sym)->som_type = SYMBOL_TYPE_ABSOLUTE;
4691       else if (symbol_type == ST_DATA)
4692 	som_symbol_data (sym)->som_type = SYMBOL_TYPE_DATA;
4693       else if (symbol_type == ST_CODE)
4694 	som_symbol_data (sym)->som_type = SYMBOL_TYPE_CODE;
4695       else if (symbol_type == ST_PRI_PROG)
4696 	som_symbol_data (sym)->som_type = SYMBOL_TYPE_PRI_PROG;
4697       else if (symbol_type == ST_SEC_PROG)
4698 	som_symbol_data (sym)->som_type = SYMBOL_TYPE_SEC_PROG;
4699       else if (symbol_type == ST_ENTRY)
4700 	som_symbol_data (sym)->som_type = SYMBOL_TYPE_ENTRY;
4701       else if (symbol_type == ST_MILLICODE)
4702 	som_symbol_data (sym)->som_type = SYMBOL_TYPE_MILLICODE;
4703       else if (symbol_type == ST_PLABEL)
4704 	som_symbol_data (sym)->som_type = SYMBOL_TYPE_PLABEL;
4705       else
4706 	som_symbol_data (sym)->som_type = SYMBOL_TYPE_UNKNOWN;
4707       som_symbol_data (sym)->tc_data.ap.hppa_arg_reloc =
4708 	(flags >> SOM_SYMBOL_ARG_RELOC_SH) & SOM_SYMBOL_ARG_RELOC_MASK;
4709 
4710       /* Some reasonable defaults.  */
4711       sym->symbol.the_bfd = abfd;
4712       sym->symbol.name = bfd_getb32 (bufp->name) + stringtab;
4713       sym->symbol.value = bfd_getb32 (bufp->symbol_value);
4714       sym->symbol.section = 0;
4715       sym->symbol.flags = 0;
4716 
4717       switch (symbol_type)
4718 	{
4719 	case ST_ENTRY:
4720 	case ST_MILLICODE:
4721 	  sym->symbol.flags |= BSF_FUNCTION;
4722 	  som_symbol_data (sym)->tc_data.ap.hppa_priv_level =
4723 	    sym->symbol.value & 0x3;
4724 	  sym->symbol.value &= ~0x3;
4725 	  break;
4726 
4727 	case ST_STUB:
4728 	case ST_CODE:
4729 	case ST_PRI_PROG:
4730 	case ST_SEC_PROG:
4731 	  som_symbol_data (sym)->tc_data.ap.hppa_priv_level =
4732 	    sym->symbol.value & 0x3;
4733 	  sym->symbol.value &= ~0x3;
4734 	  /* If the symbol's scope is SS_UNSAT, then these are
4735 	     undefined function symbols.  */
4736 	  if (symbol_scope == SS_UNSAT)
4737 	    sym->symbol.flags |= BSF_FUNCTION;
4738 
4739 	default:
4740 	  break;
4741 	}
4742 
4743       /* Handle scoping and section information.  */
4744       switch (symbol_scope)
4745 	{
4746 	/* symbol_info field is undefined for SS_EXTERNAL and SS_UNSAT symbols,
4747 	   so the section associated with this symbol can't be known.  */
4748 	case SS_EXTERNAL:
4749 	  if (symbol_type != ST_STORAGE)
4750 	    sym->symbol.section = bfd_und_section_ptr;
4751 	  else
4752 	    sym->symbol.section = bfd_com_section_ptr;
4753 	  sym->symbol.flags |= (BSF_EXPORT | BSF_GLOBAL);
4754 	  break;
4755 
4756 	case SS_UNSAT:
4757 	  if (symbol_type != ST_STORAGE)
4758 	    sym->symbol.section = bfd_und_section_ptr;
4759 	  else
4760 	    sym->symbol.section = bfd_com_section_ptr;
4761 	  break;
4762 
4763 	case SS_UNIVERSAL:
4764 	  sym->symbol.flags |= (BSF_EXPORT | BSF_GLOBAL);
4765 	  sym->symbol.section = bfd_section_from_som_symbol (abfd, bufp);
4766 	  sym->symbol.value -= sym->symbol.section->vma;
4767 	  break;
4768 
4769 	case SS_LOCAL:
4770 	  sym->symbol.flags |= BSF_LOCAL;
4771 	  sym->symbol.section = bfd_section_from_som_symbol (abfd, bufp);
4772 	  sym->symbol.value -= sym->symbol.section->vma;
4773 	  break;
4774 	}
4775 
4776       /* Check for a weak symbol.  */
4777       if (flags & SOM_SYMBOL_SECONDARY_DEF)
4778 	sym->symbol.flags |= BSF_WEAK;
4779 
4780       /* Mark section symbols and symbols used by the debugger.
4781 	 Note $START$ is a magic code symbol, NOT a section symbol.  */
4782       if (sym->symbol.name[0] == '$'
4783 	  && sym->symbol.name[strlen (sym->symbol.name) - 1] == '$'
4784 	  && !strcmp (sym->symbol.name, sym->symbol.section->name))
4785 	sym->symbol.flags |= BSF_SECTION_SYM;
4786       else if (CONST_STRNEQ (sym->symbol.name, "L$0\002"))
4787 	{
4788 	  sym->symbol.flags |= BSF_SECTION_SYM;
4789 	  sym->symbol.name = sym->symbol.section->name;
4790 	}
4791       else if (CONST_STRNEQ (sym->symbol.name, "L$0\001"))
4792 	sym->symbol.flags |= BSF_DEBUGGING;
4793 
4794       /* Note increment at bottom of loop, since we skip some symbols
4795 	 we can not include it as part of the for statement.  */
4796       sym++;
4797     }
4798 
4799   /* We modify the symbol count to record the number of BFD symbols we
4800      created.  */
4801   abfd->symcount = sym - symbase;
4802 
4803   /* Save our results and return success.  */
4804   obj_som_symtab (abfd) = symbase;
4805  successful_return:
4806   if (buf != NULL)
4807     free (buf);
4808   return (TRUE);
4809 
4810  error_return:
4811   if (buf != NULL)
4812     free (buf);
4813   return FALSE;
4814 }
4815 
4816 /* Canonicalize a SOM symbol table.  Return the number of entries
4817    in the symbol table.  */
4818 
4819 static long
4820 som_canonicalize_symtab (bfd *abfd, asymbol **location)
4821 {
4822   int i;
4823   som_symbol_type *symbase;
4824 
4825   if (!som_slurp_symbol_table (abfd))
4826     return -1;
4827 
4828   i = bfd_get_symcount (abfd);
4829   symbase = obj_som_symtab (abfd);
4830 
4831   for (; i > 0; i--, location++, symbase++)
4832     *location = &symbase->symbol;
4833 
4834   /* Final null pointer.  */
4835   *location = 0;
4836   return (bfd_get_symcount (abfd));
4837 }
4838 
4839 /* Make a SOM symbol.  There is nothing special to do here.  */
4840 
4841 static asymbol *
4842 som_make_empty_symbol (bfd *abfd)
4843 {
4844   bfd_size_type amt = sizeof (som_symbol_type);
4845   som_symbol_type *new_symbol_type = bfd_zalloc (abfd, amt);
4846 
4847   if (new_symbol_type == NULL)
4848     return NULL;
4849   new_symbol_type->symbol.the_bfd = abfd;
4850 
4851   return &new_symbol_type->symbol;
4852 }
4853 
4854 /* Print symbol information.  */
4855 
4856 static void
4857 som_print_symbol (bfd *abfd,
4858 		  void *afile,
4859 		  asymbol *symbol,
4860 		  bfd_print_symbol_type how)
4861 {
4862   FILE *file = (FILE *) afile;
4863 
4864   switch (how)
4865     {
4866     case bfd_print_symbol_name:
4867       fprintf (file, "%s", symbol->name);
4868       break;
4869     case bfd_print_symbol_more:
4870       fprintf (file, "som ");
4871       fprintf_vma (file, symbol->value);
4872       fprintf (file, " %lx", (long) symbol->flags);
4873       break;
4874     case bfd_print_symbol_all:
4875       {
4876 	const char *section_name;
4877 
4878 	section_name = symbol->section ? symbol->section->name : "(*none*)";
4879 	bfd_print_symbol_vandf (abfd, (void *) file, symbol);
4880 	fprintf (file, " %s\t%s", section_name, symbol->name);
4881 	break;
4882       }
4883     }
4884 }
4885 
4886 static bfd_boolean
4887 som_bfd_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED,
4888 			     const char *name)
4889 {
4890   return name[0] == 'L' && name[1] == '$';
4891 }
4892 
4893 /* Count or process variable-length SOM fixup records.
4894 
4895    To avoid code duplication we use this code both to compute the number
4896    of relocations requested by a stream, and to internalize the stream.
4897 
4898    When computing the number of relocations requested by a stream the
4899    variables rptr, section, and symbols have no meaning.
4900 
4901    Return the number of relocations requested by the fixup stream.  When
4902    not just counting
4903 
4904    This needs at least two or three more passes to get it cleaned up.  */
4905 
4906 static unsigned int
4907 som_set_reloc_info (unsigned char *fixup,
4908 		    unsigned int end,
4909 		    arelent *internal_relocs,
4910 		    asection *section,
4911 		    asymbol **symbols,
4912 		    bfd_boolean just_count)
4913 {
4914   unsigned int op, varname, deallocate_contents = 0;
4915   unsigned char *end_fixups = &fixup[end];
4916   const struct fixup_format *fp;
4917   const char *cp;
4918   unsigned char *save_fixup;
4919   int variables[26], stack[20], c, v, count, prev_fixup, *sp, saved_unwind_bits;
4920   const int *subop;
4921   arelent *rptr = internal_relocs;
4922   unsigned int offset = 0;
4923 
4924 #define	var(c)		variables[(c) - 'A']
4925 #define	push(v)		(*sp++ = (v))
4926 #define	pop()		(*--sp)
4927 #define	emptystack()	(sp == stack)
4928 
4929   som_initialize_reloc_queue (reloc_queue);
4930   memset (variables, 0, sizeof (variables));
4931   memset (stack, 0, sizeof (stack));
4932   count = 0;
4933   prev_fixup = 0;
4934   saved_unwind_bits = 0;
4935   sp = stack;
4936 
4937   while (fixup < end_fixups)
4938     {
4939       /* Save pointer to the start of this fixup.  We'll use
4940 	 it later to determine if it is necessary to put this fixup
4941 	 on the queue.  */
4942       save_fixup = fixup;
4943 
4944       /* Get the fixup code and its associated format.  */
4945       op = *fixup++;
4946       fp = &som_fixup_formats[op];
4947 
4948       /* Handle a request for a previous fixup.  */
4949       if (*fp->format == 'P')
4950 	{
4951 	  /* Get pointer to the beginning of the prev fixup, move
4952 	     the repeated fixup to the head of the queue.  */
4953 	  fixup = reloc_queue[fp->D].reloc;
4954 	  som_reloc_queue_fix (reloc_queue, fp->D);
4955 	  prev_fixup = 1;
4956 
4957 	  /* Get the fixup code and its associated format.  */
4958 	  op = *fixup++;
4959 	  fp = &som_fixup_formats[op];
4960 	}
4961 
4962       /* If this fixup will be passed to BFD, set some reasonable defaults.  */
4963       if (! just_count
4964 	  && som_hppa_howto_table[op].type != R_NO_RELOCATION
4965 	  && som_hppa_howto_table[op].type != R_DATA_OVERRIDE)
4966 	{
4967 	  rptr->address = offset;
4968 	  rptr->howto = &som_hppa_howto_table[op];
4969 	  rptr->addend = 0;
4970 	  rptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
4971 	}
4972 
4973       /* Set default input length to 0.  Get the opcode class index
4974 	 into D.  */
4975       var ('L') = 0;
4976       var ('D') = fp->D;
4977       var ('U') = saved_unwind_bits;
4978 
4979       /* Get the opcode format.  */
4980       cp = fp->format;
4981 
4982       /* Process the format string.  Parsing happens in two phases,
4983 	 parse RHS, then assign to LHS.  Repeat until no more
4984 	 characters in the format string.  */
4985       while (*cp)
4986 	{
4987 	  /* The variable this pass is going to compute a value for.  */
4988 	  varname = *cp++;
4989 
4990 	  /* Start processing RHS.  Continue until a NULL or '=' is found.  */
4991 	  do
4992 	    {
4993 	      c = *cp++;
4994 
4995 	      /* If this is a variable, push it on the stack.  */
4996 	      if (ISUPPER (c))
4997 		push (var (c));
4998 
4999 	      /* If this is a lower case letter, then it represents
5000 		 additional data from the fixup stream to be pushed onto
5001 		 the stack.  */
5002 	      else if (ISLOWER (c))
5003 		{
5004 		  int bits = (c - 'a') * 8;
5005 		  for (v = 0; c > 'a'; --c)
5006 		    v = (v << 8) | *fixup++;
5007 		  if (varname == 'V')
5008 		    v = sign_extend (v, bits);
5009 		  push (v);
5010 		}
5011 
5012 	      /* A decimal constant.  Push it on the stack.  */
5013 	      else if (ISDIGIT (c))
5014 		{
5015 		  v = c - '0';
5016 		  while (ISDIGIT (*cp))
5017 		    v = (v * 10) + (*cp++ - '0');
5018 		  push (v);
5019 		}
5020 	      else
5021 		/* An operator.  Pop two values from the stack and
5022 		   use them as operands to the given operation.  Push
5023 		   the result of the operation back on the stack.  */
5024 		switch (c)
5025 		  {
5026 		  case '+':
5027 		    v = pop ();
5028 		    v += pop ();
5029 		    push (v);
5030 		    break;
5031 		  case '*':
5032 		    v = pop ();
5033 		    v *= pop ();
5034 		    push (v);
5035 		    break;
5036 		  case '<':
5037 		    v = pop ();
5038 		    v = pop () << v;
5039 		    push (v);
5040 		    break;
5041 		  default:
5042 		    abort ();
5043 		  }
5044 	    }
5045 	  while (*cp && *cp != '=');
5046 
5047 	  /* Move over the equal operator.  */
5048 	  cp++;
5049 
5050 	  /* Pop the RHS off the stack.  */
5051 	  c = pop ();
5052 
5053 	  /* Perform the assignment.  */
5054 	  var (varname) = c;
5055 
5056 	  /* Handle side effects. and special 'O' stack cases.  */
5057 	  switch (varname)
5058 	    {
5059 	    /* Consume some bytes from the input space.  */
5060 	    case 'L':
5061 	      offset += c;
5062 	      break;
5063 	    /* A symbol to use in the relocation.  Make a note
5064 	       of this if we are not just counting.  */
5065 	    case 'S':
5066 	      if (! just_count)
5067 		rptr->sym_ptr_ptr = &symbols[c];
5068 	      break;
5069 	    /* Argument relocation bits for a function call.  */
5070 	    case 'R':
5071 	      if (! just_count)
5072 		{
5073 		  unsigned int tmp = var ('R');
5074 		  rptr->addend = 0;
5075 
5076 		  if ((som_hppa_howto_table[op].type == R_PCREL_CALL
5077 		       && R_PCREL_CALL + 10 > op)
5078 		      || (som_hppa_howto_table[op].type == R_ABS_CALL
5079 			  && R_ABS_CALL + 10 > op))
5080 		    {
5081 		      /* Simple encoding.  */
5082 		      if (tmp > 4)
5083 			{
5084 			  tmp -= 5;
5085 			  rptr->addend |= 1;
5086 			}
5087 		      if (tmp == 4)
5088 			rptr->addend |= 1 << 8 | 1 << 6 | 1 << 4 | 1 << 2;
5089 		      else if (tmp == 3)
5090 			rptr->addend |= 1 << 8 | 1 << 6 | 1 << 4;
5091 		      else if (tmp == 2)
5092 			rptr->addend |= 1 << 8 | 1 << 6;
5093 		      else if (tmp == 1)
5094 			rptr->addend |= 1 << 8;
5095 		    }
5096 		  else
5097 		    {
5098 		      unsigned int tmp1, tmp2;
5099 
5100 		      /* First part is easy -- low order two bits are
5101 			 directly copied, then shifted away.  */
5102 		      rptr->addend = tmp & 0x3;
5103 		      tmp >>= 2;
5104 
5105 		      /* Diving the result by 10 gives us the second
5106 			 part.  If it is 9, then the first two words
5107 			 are a double precision paramater, else it is
5108 			 3 * the first arg bits + the 2nd arg bits.  */
5109 		      tmp1 = tmp / 10;
5110 		      tmp -= tmp1 * 10;
5111 		      if (tmp1 == 9)
5112 			rptr->addend += (0xe << 6);
5113 		      else
5114 			{
5115 			  /* Get the two pieces.  */
5116 			  tmp2 = tmp1 / 3;
5117 			  tmp1 -= tmp2 * 3;
5118 			  /* Put them in the addend.  */
5119 			  rptr->addend += (tmp2 << 8) + (tmp1 << 6);
5120 			}
5121 
5122 		      /* What's left is the third part.  It's unpacked
5123 			 just like the second.  */
5124 		      if (tmp == 9)
5125 			rptr->addend += (0xe << 2);
5126 		      else
5127 			{
5128 			  tmp2 = tmp / 3;
5129 			  tmp -= tmp2 * 3;
5130 			  rptr->addend += (tmp2 << 4) + (tmp << 2);
5131 			}
5132 		    }
5133 		  rptr->addend = HPPA_R_ADDEND (rptr->addend, 0);
5134 		}
5135 	      break;
5136 	    /* Handle the linker expression stack.  */
5137 	    case 'O':
5138 	      switch (op)
5139 		{
5140 		case R_COMP1:
5141 		  subop = comp1_opcodes;
5142 		  break;
5143 		case R_COMP2:
5144 		  subop = comp2_opcodes;
5145 		  break;
5146 		case R_COMP3:
5147 		  subop = comp3_opcodes;
5148 		  break;
5149 		default:
5150 		  abort ();
5151 		}
5152 	      while (*subop <= (unsigned char) c)
5153 		++subop;
5154 	      --subop;
5155 	      break;
5156 	    /* The lower 32unwind bits must be persistent.  */
5157 	    case 'U':
5158 	      saved_unwind_bits = var ('U');
5159 	      break;
5160 
5161 	    default:
5162 	      break;
5163 	    }
5164 	}
5165 
5166       /* If we used a previous fixup, clean up after it.  */
5167       if (prev_fixup)
5168 	{
5169 	  fixup = save_fixup + 1;
5170 	  prev_fixup = 0;
5171 	}
5172       /* Queue it.  */
5173       else if (fixup > save_fixup + 1)
5174 	som_reloc_queue_insert (save_fixup, fixup - save_fixup, reloc_queue);
5175 
5176       /* We do not pass R_DATA_OVERRIDE or R_NO_RELOCATION
5177 	 fixups to BFD.  */
5178       if (som_hppa_howto_table[op].type != R_DATA_OVERRIDE
5179 	  && som_hppa_howto_table[op].type != R_NO_RELOCATION)
5180 	{
5181 	  /* Done with a single reloction. Loop back to the top.  */
5182 	  if (! just_count)
5183 	    {
5184 	      if (som_hppa_howto_table[op].type == R_ENTRY)
5185 		rptr->addend = var ('T');
5186 	      else if (som_hppa_howto_table[op].type == R_EXIT)
5187 		rptr->addend = var ('U');
5188 	      else if (som_hppa_howto_table[op].type == R_PCREL_CALL
5189 		       || som_hppa_howto_table[op].type == R_ABS_CALL)
5190 		;
5191 	      else if (som_hppa_howto_table[op].type == R_DATA_ONE_SYMBOL)
5192 		{
5193 		  /* Try what was specified in R_DATA_OVERRIDE first
5194 		     (if anything).  Then the hard way using the
5195 		     section contents.  */
5196 		  rptr->addend = var ('V');
5197 
5198 		  if (rptr->addend == 0 && !section->contents)
5199 		    {
5200 		      /* Got to read the damn contents first.  We don't
5201 			 bother saving the contents (yet).  Add it one
5202 			 day if the need arises.  */
5203 		      bfd_byte *contents;
5204 		      if (!bfd_malloc_and_get_section (section->owner, section,
5205 						       &contents))
5206 			{
5207 			  if (contents != NULL)
5208 			    free (contents);
5209 			  return (unsigned) -1;
5210 			}
5211 		      section->contents = contents;
5212 		      deallocate_contents = 1;
5213 		    }
5214 		  else if (rptr->addend == 0)
5215 		    rptr->addend = bfd_get_32 (section->owner,
5216 					       (section->contents
5217 						+ offset - var ('L')));
5218 
5219 		}
5220 	      else
5221 		rptr->addend = var ('V');
5222 	      rptr++;
5223 	    }
5224 	  count++;
5225 	  /* Now that we've handled a "full" relocation, reset
5226 	     some state.  */
5227 	  memset (variables, 0, sizeof (variables));
5228 	  memset (stack, 0, sizeof (stack));
5229 	}
5230     }
5231   if (deallocate_contents)
5232     free (section->contents);
5233 
5234   return count;
5235 
5236 #undef var
5237 #undef push
5238 #undef pop
5239 #undef emptystack
5240 }
5241 
5242 /* Read in the relocs (aka fixups in SOM terms) for a section.
5243 
5244    som_get_reloc_upper_bound calls this routine with JUST_COUNT
5245    set to TRUE to indicate it only needs a count of the number
5246    of actual relocations.  */
5247 
5248 static bfd_boolean
5249 som_slurp_reloc_table (bfd *abfd,
5250 		       asection *section,
5251 		       asymbol **symbols,
5252 		       bfd_boolean just_count)
5253 {
5254   unsigned char *external_relocs;
5255   unsigned int fixup_stream_size;
5256   arelent *internal_relocs;
5257   unsigned int num_relocs;
5258   bfd_size_type amt;
5259 
5260   fixup_stream_size = som_section_data (section)->reloc_size;
5261   /* If there were no relocations, then there is nothing to do.  */
5262   if (section->reloc_count == 0)
5263     return TRUE;
5264 
5265   /* If reloc_count is -1, then the relocation stream has not been
5266      parsed.  We must do so now to know how many relocations exist.  */
5267   if (section->reloc_count == (unsigned) -1)
5268     {
5269       amt = fixup_stream_size;
5270       external_relocs = bfd_malloc (amt);
5271       if (external_relocs == NULL)
5272 	return FALSE;
5273       /* Read in the external forms.  */
5274       if (bfd_seek (abfd,
5275 		    obj_som_reloc_filepos (abfd) + section->rel_filepos,
5276 		    SEEK_SET)
5277 	  != 0)
5278 	return FALSE;
5279       if (bfd_bread (external_relocs, amt, abfd) != amt)
5280 	return FALSE;
5281 
5282       /* Let callers know how many relocations found.
5283 	 also save the relocation stream as we will
5284 	 need it again.  */
5285       section->reloc_count = som_set_reloc_info (external_relocs,
5286 						 fixup_stream_size,
5287 						 NULL, NULL, NULL, TRUE);
5288 
5289       som_section_data (section)->reloc_stream = external_relocs;
5290     }
5291 
5292   /* If the caller only wanted a count, then return now.  */
5293   if (just_count)
5294     return TRUE;
5295 
5296   num_relocs = section->reloc_count;
5297   external_relocs = som_section_data (section)->reloc_stream;
5298   /* Return saved information about the relocations if it is available.  */
5299   if (section->relocation != NULL)
5300     return TRUE;
5301 
5302   internal_relocs = bfd_zalloc2 (abfd, num_relocs, sizeof (arelent));
5303   if (internal_relocs == NULL)
5304     return FALSE;
5305 
5306   /* Process and internalize the relocations.  */
5307   som_set_reloc_info (external_relocs, fixup_stream_size,
5308 		      internal_relocs, section, symbols, FALSE);
5309 
5310   /* We're done with the external relocations.  Free them.  */
5311   free (external_relocs);
5312   som_section_data (section)->reloc_stream = NULL;
5313 
5314   /* Save our results and return success.  */
5315   section->relocation = internal_relocs;
5316   return TRUE;
5317 }
5318 
5319 /* Return the number of bytes required to store the relocation
5320    information associated with the given section.  */
5321 
5322 static long
5323 som_get_reloc_upper_bound (bfd *abfd, sec_ptr asect)
5324 {
5325   /* If section has relocations, then read in the relocation stream
5326      and parse it to determine how many relocations exist.  */
5327   if (asect->flags & SEC_RELOC)
5328     {
5329       if (! som_slurp_reloc_table (abfd, asect, NULL, TRUE))
5330 	return -1;
5331       return (asect->reloc_count + 1) * sizeof (arelent *);
5332     }
5333 
5334   /* There are no relocations.  Return enough space to hold the
5335      NULL pointer which will be installed if som_canonicalize_reloc
5336      is called.  */
5337   return sizeof (arelent *);
5338 }
5339 
5340 /* Convert relocations from SOM (external) form into BFD internal
5341    form.  Return the number of relocations.  */
5342 
5343 static long
5344 som_canonicalize_reloc (bfd *abfd,
5345 			sec_ptr section,
5346 			arelent **relptr,
5347 			asymbol **symbols)
5348 {
5349   arelent *tblptr;
5350   int count;
5351 
5352   if (! som_slurp_reloc_table (abfd, section, symbols, FALSE))
5353     return -1;
5354 
5355   count = section->reloc_count;
5356   tblptr = section->relocation;
5357 
5358   while (count--)
5359     *relptr++ = tblptr++;
5360 
5361   *relptr = NULL;
5362   return section->reloc_count;
5363 }
5364 
5365 extern const bfd_target hppa_som_vec;
5366 
5367 /* A hook to set up object file dependent section information.  */
5368 
5369 static bfd_boolean
5370 som_new_section_hook (bfd *abfd, asection *newsect)
5371 {
5372   if (!newsect->used_by_bfd)
5373     {
5374       bfd_size_type amt = sizeof (struct som_section_data_struct);
5375 
5376       newsect->used_by_bfd = bfd_zalloc (abfd, amt);
5377       if (!newsect->used_by_bfd)
5378 	return FALSE;
5379     }
5380   newsect->alignment_power = 3;
5381 
5382   /* We allow more than three sections internally.  */
5383   return _bfd_generic_new_section_hook (abfd, newsect);
5384 }
5385 
5386 /* Copy any private info we understand from the input symbol
5387    to the output symbol.  */
5388 
5389 static bfd_boolean
5390 som_bfd_copy_private_symbol_data (bfd *ibfd,
5391 				  asymbol *isymbol,
5392 				  bfd *obfd,
5393 				  asymbol *osymbol)
5394 {
5395   struct som_symbol *input_symbol = (struct som_symbol *) isymbol;
5396   struct som_symbol *output_symbol = (struct som_symbol *) osymbol;
5397 
5398   /* One day we may try to grok other private data.  */
5399   if (ibfd->xvec->flavour != bfd_target_som_flavour
5400       || obfd->xvec->flavour != bfd_target_som_flavour)
5401     return FALSE;
5402 
5403   /* The only private information we need to copy is the argument relocation
5404      bits.  */
5405   output_symbol->tc_data.ap.hppa_arg_reloc =
5406     input_symbol->tc_data.ap.hppa_arg_reloc;
5407 
5408   return TRUE;
5409 }
5410 
5411 /* Copy any private info we understand from the input section
5412    to the output section.  */
5413 
5414 static bfd_boolean
5415 som_bfd_copy_private_section_data (bfd *ibfd,
5416 				   asection *isection,
5417 				   bfd *obfd,
5418 				   asection *osection)
5419 {
5420   bfd_size_type amt;
5421 
5422   /* One day we may try to grok other private data.  */
5423   if (ibfd->xvec->flavour != bfd_target_som_flavour
5424       || obfd->xvec->flavour != bfd_target_som_flavour
5425       || (!som_is_space (isection) && !som_is_subspace (isection)))
5426     return TRUE;
5427 
5428   amt = sizeof (struct som_copyable_section_data_struct);
5429   som_section_data (osection)->copy_data = bfd_zalloc (obfd, amt);
5430   if (som_section_data (osection)->copy_data == NULL)
5431     return FALSE;
5432 
5433   memcpy (som_section_data (osection)->copy_data,
5434 	  som_section_data (isection)->copy_data,
5435 	  sizeof (struct som_copyable_section_data_struct));
5436 
5437   /* Reparent if necessary.  */
5438   if (som_section_data (osection)->copy_data->container)
5439     som_section_data (osection)->copy_data->container =
5440       som_section_data (osection)->copy_data->container->output_section;
5441 
5442   return TRUE;
5443 }
5444 
5445 /* Copy any private info we understand from the input bfd
5446    to the output bfd.  */
5447 
5448 static bfd_boolean
5449 som_bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
5450 {
5451   /* One day we may try to grok other private data.  */
5452   if (ibfd->xvec->flavour != bfd_target_som_flavour
5453       || obfd->xvec->flavour != bfd_target_som_flavour)
5454     return TRUE;
5455 
5456   /* Allocate some memory to hold the data we need.  */
5457   obj_som_exec_data (obfd) = bfd_zalloc (obfd, (bfd_size_type) sizeof (struct som_exec_data));
5458   if (obj_som_exec_data (obfd) == NULL)
5459     return FALSE;
5460 
5461   /* Now copy the data.  */
5462   memcpy (obj_som_exec_data (obfd), obj_som_exec_data (ibfd),
5463 	  sizeof (struct som_exec_data));
5464 
5465   return TRUE;
5466 }
5467 
5468 /* Display the SOM header.  */
5469 
5470 static bfd_boolean
5471 som_bfd_print_private_bfd_data (bfd *abfd, void *farg)
5472 {
5473   struct som_exec_auxhdr *exec_header;
5474   struct som_aux_id* auxhdr;
5475   FILE *f;
5476 
5477   f = (FILE *) farg;
5478 
5479   exec_header = obj_som_exec_hdr (abfd);
5480   if (exec_header)
5481     {
5482       fprintf (f, _("\nExec Auxiliary Header\n"));
5483       fprintf (f, "  flags              ");
5484       auxhdr = &exec_header->som_auxhdr;
5485       if (auxhdr->mandatory)
5486 	fprintf (f, "mandatory ");
5487       if (auxhdr->copy)
5488 	fprintf (f, "copy ");
5489       if (auxhdr->append)
5490 	fprintf (f, "append ");
5491       if (auxhdr->ignore)
5492 	fprintf (f, "ignore ");
5493       fprintf (f, "\n");
5494       fprintf (f, "  type               %#x\n", auxhdr->type);
5495       fprintf (f, "  length             %#x\n", auxhdr->length);
5496 
5497       /* Note that, depending on the HP-UX version, the following fields can be
5498 	 either ints, or longs.  */
5499 
5500       fprintf (f, "  text size          %#lx\n", (long) exec_header->exec_tsize);
5501       fprintf (f, "  text memory offset %#lx\n", (long) exec_header->exec_tmem);
5502       fprintf (f, "  text file offset   %#lx\n", (long) exec_header->exec_tfile);
5503       fprintf (f, "  data size          %#lx\n", (long) exec_header->exec_dsize);
5504       fprintf (f, "  data memory offset %#lx\n", (long) exec_header->exec_dmem);
5505       fprintf (f, "  data file offset   %#lx\n", (long) exec_header->exec_dfile);
5506       fprintf (f, "  bss size           %#lx\n", (long) exec_header->exec_bsize);
5507       fprintf (f, "  entry point        %#lx\n", (long) exec_header->exec_entry);
5508       fprintf (f, "  loader flags       %#lx\n", (long) exec_header->exec_flags);
5509       fprintf (f, "  bss initializer    %#lx\n", (long) exec_header->exec_bfill);
5510     }
5511 
5512   return TRUE;
5513 }
5514 
5515 /* Set backend info for sections which can not be described
5516    in the BFD data structures.  */
5517 
5518 bfd_boolean
5519 bfd_som_set_section_attributes (asection *section,
5520 				int defined,
5521 				int private,
5522 				unsigned int sort_key,
5523 				int spnum)
5524 {
5525   /* Allocate memory to hold the magic information.  */
5526   if (som_section_data (section)->copy_data == NULL)
5527     {
5528       bfd_size_type amt = sizeof (struct som_copyable_section_data_struct);
5529 
5530       som_section_data (section)->copy_data = bfd_zalloc (section->owner, amt);
5531       if (som_section_data (section)->copy_data == NULL)
5532 	return FALSE;
5533     }
5534   som_section_data (section)->copy_data->sort_key = sort_key;
5535   som_section_data (section)->copy_data->is_defined = defined;
5536   som_section_data (section)->copy_data->is_private = private;
5537   som_section_data (section)->copy_data->container = section;
5538   som_section_data (section)->copy_data->space_number = spnum;
5539   return TRUE;
5540 }
5541 
5542 /* Set backend info for subsections which can not be described
5543    in the BFD data structures.  */
5544 
5545 bfd_boolean
5546 bfd_som_set_subsection_attributes (asection *section,
5547 				   asection *container,
5548 				   int access_ctr,
5549 				   unsigned int sort_key,
5550 				   int quadrant,
5551 				   int comdat,
5552 				   int common,
5553 				   int dup_common)
5554 {
5555   /* Allocate memory to hold the magic information.  */
5556   if (som_section_data (section)->copy_data == NULL)
5557     {
5558       bfd_size_type amt = sizeof (struct som_copyable_section_data_struct);
5559 
5560       som_section_data (section)->copy_data = bfd_zalloc (section->owner, amt);
5561       if (som_section_data (section)->copy_data == NULL)
5562 	return FALSE;
5563     }
5564   som_section_data (section)->copy_data->sort_key = sort_key;
5565   som_section_data (section)->copy_data->access_control_bits = access_ctr;
5566   som_section_data (section)->copy_data->quadrant = quadrant;
5567   som_section_data (section)->copy_data->container = container;
5568   som_section_data (section)->copy_data->is_comdat = comdat;
5569   som_section_data (section)->copy_data->is_common = common;
5570   som_section_data (section)->copy_data->dup_common = dup_common;
5571   return TRUE;
5572 }
5573 
5574 /* Set the full SOM symbol type.  SOM needs far more symbol information
5575    than any other object file format I'm aware of.  It is mandatory
5576    to be able to know if a symbol is an entry point, millicode, data,
5577    code, absolute, storage request, or procedure label.  If you get
5578    the symbol type wrong your program will not link.  */
5579 
5580 void
5581 bfd_som_set_symbol_type (asymbol *symbol, unsigned int type)
5582 {
5583   som_symbol_data (symbol)->som_type = type;
5584 }
5585 
5586 /* Attach an auxiliary header to the BFD backend so that it may be
5587    written into the object file.  */
5588 
5589 bfd_boolean
5590 bfd_som_attach_aux_hdr (bfd *abfd, int type, char *string)
5591 {
5592   bfd_size_type amt;
5593 
5594   if (type == VERSION_AUX_ID)
5595     {
5596       size_t len = strlen (string);
5597       int pad = 0;
5598 
5599       if (len % 4)
5600 	pad = (4 - (len % 4));
5601       amt = sizeof (struct som_string_auxhdr) + len + pad;
5602       obj_som_version_hdr (abfd) = bfd_zalloc (abfd, amt);
5603       if (!obj_som_version_hdr (abfd))
5604 	return FALSE;
5605       obj_som_version_hdr (abfd)->header_id.type = VERSION_AUX_ID;
5606       obj_som_version_hdr (abfd)->header_id.length = 4 + len + pad;
5607       obj_som_version_hdr (abfd)->string_length = len;
5608       memcpy (obj_som_version_hdr (abfd)->string, string, len);
5609       memset (obj_som_version_hdr (abfd)->string + len, 0, pad);
5610     }
5611   else if (type == COPYRIGHT_AUX_ID)
5612     {
5613       size_t len = strlen (string);
5614       int pad = 0;
5615 
5616       if (len % 4)
5617 	pad = (4 - (len % 4));
5618       amt = sizeof (struct som_string_auxhdr) + len + pad;
5619       obj_som_copyright_hdr (abfd) = bfd_zalloc (abfd, amt);
5620       if (!obj_som_copyright_hdr (abfd))
5621 	return FALSE;
5622       obj_som_copyright_hdr (abfd)->header_id.type = COPYRIGHT_AUX_ID;
5623       obj_som_copyright_hdr (abfd)->header_id.length = len + pad + 4;
5624       obj_som_copyright_hdr (abfd)->string_length = len;
5625       memcpy (obj_som_copyright_hdr (abfd)->string, string, len);
5626       memset (obj_som_copyright_hdr (abfd)->string + len, 0, pad);
5627     }
5628   return TRUE;
5629 }
5630 
5631 /* Attach a compilation unit header to the BFD backend so that it may be
5632    written into the object file.  */
5633 
5634 bfd_boolean
5635 bfd_som_attach_compilation_unit (bfd *abfd,
5636 				 const char *name,
5637 				 const char *language_name,
5638 				 const char *product_id,
5639 				 const char *version_id)
5640 {
5641   struct som_compilation_unit *n;
5642 
5643   n = (struct som_compilation_unit *) bfd_zalloc
5644     (abfd, (bfd_size_type) sizeof (*n));
5645   if (n == NULL)
5646     return FALSE;
5647 
5648 #define STRDUP(f) \
5649   if (f != NULL) \
5650     { \
5651       n->f.name = bfd_alloc (abfd, (bfd_size_type) strlen (f) + 1); \
5652       if (n->f.name == NULL) \
5653 	return FALSE; \
5654       strcpy (n->f.name, f); \
5655     }
5656 
5657   STRDUP (name);
5658   STRDUP (language_name);
5659   STRDUP (product_id);
5660   STRDUP (version_id);
5661 
5662 #undef STRDUP
5663 
5664   obj_som_compilation_unit (abfd) = n;
5665 
5666   return TRUE;
5667 }
5668 
5669 static bfd_boolean
5670 som_get_section_contents (bfd *abfd,
5671 			  sec_ptr section,
5672 			  void *location,
5673 			  file_ptr offset,
5674 			  bfd_size_type count)
5675 {
5676   if (count == 0 || ((section->flags & SEC_HAS_CONTENTS) == 0))
5677     return TRUE;
5678   if ((bfd_size_type) (offset+count) > section->size
5679       || bfd_seek (abfd, (file_ptr) (section->filepos + offset), SEEK_SET) != 0
5680       || bfd_bread (location, count, abfd) != count)
5681     return FALSE; /* On error.  */
5682   return TRUE;
5683 }
5684 
5685 static bfd_boolean
5686 som_set_section_contents (bfd *abfd,
5687 			  sec_ptr section,
5688 			  const void *location,
5689 			  file_ptr offset,
5690 			  bfd_size_type count)
5691 {
5692   if (! abfd->output_has_begun)
5693     {
5694       /* Set up fixed parts of the file, space, and subspace headers.
5695 	 Notify the world that output has begun.  */
5696       som_prep_headers (abfd);
5697       abfd->output_has_begun = TRUE;
5698       /* Start writing the object file.  This include all the string
5699 	 tables, fixup streams, and other portions of the object file.  */
5700       som_begin_writing (abfd);
5701     }
5702 
5703   /* Only write subspaces which have "real" contents (eg. the contents
5704      are not generated at run time by the OS).  */
5705   if (!som_is_subspace (section)
5706       || ((section->flags & SEC_HAS_CONTENTS) == 0))
5707     return TRUE;
5708 
5709   /* Seek to the proper offset within the object file and write the
5710      data.  */
5711   offset += som_section_data (section)->subspace_dict->file_loc_init_value;
5712   if (bfd_seek (abfd, offset, SEEK_SET) != 0)
5713     return FALSE;
5714 
5715   if (bfd_bwrite (location, count, abfd) != count)
5716     return FALSE;
5717   return TRUE;
5718 }
5719 
5720 static bfd_boolean
5721 som_set_arch_mach (bfd *abfd,
5722 		   enum bfd_architecture arch,
5723 		   unsigned long machine)
5724 {
5725   /* Allow any architecture to be supported by the SOM backend.  */
5726   return bfd_default_set_arch_mach (abfd, arch, machine);
5727 }
5728 
5729 static bfd_boolean
5730 som_find_nearest_line (bfd *abfd,
5731 		       asymbol **symbols,
5732 		       asection *section,
5733 		       bfd_vma offset,
5734 		       const char **filename_ptr,
5735 		       const char **functionname_ptr,
5736 		       unsigned int *line_ptr,
5737 		       unsigned int *discriminator_ptr)
5738 {
5739   bfd_boolean found;
5740   asymbol *func;
5741   bfd_vma low_func;
5742   asymbol **p;
5743 
5744   if (discriminator_ptr)
5745     *discriminator_ptr = 0;
5746 
5747   if (! _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset,
5748 					     & found, filename_ptr,
5749 					     functionname_ptr, line_ptr,
5750 					     & somdata (abfd).line_info))
5751     return FALSE;
5752 
5753   if (found)
5754     return TRUE;
5755 
5756   if (symbols == NULL)
5757     return FALSE;
5758 
5759   /* Fallback: find function name from symbols table.  */
5760   func = NULL;
5761   low_func = 0;
5762 
5763   for (p = symbols; *p != NULL; p++)
5764     {
5765       som_symbol_type *q = (som_symbol_type *) *p;
5766 
5767       if (q->som_type == SYMBOL_TYPE_ENTRY
5768 	  && q->symbol.section == section
5769 	  && q->symbol.value >= low_func
5770 	  && q->symbol.value <= offset)
5771 	{
5772 	  func = (asymbol *) q;
5773 	  low_func = q->symbol.value;
5774 	}
5775     }
5776 
5777   if (func == NULL)
5778     return FALSE;
5779 
5780   *filename_ptr = NULL;
5781   *functionname_ptr = bfd_asymbol_name (func);
5782   *line_ptr = 0;
5783 
5784   return TRUE;
5785 }
5786 
5787 static int
5788 som_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
5789 		    struct bfd_link_info *info ATTRIBUTE_UNUSED)
5790 {
5791   _bfd_error_handler (_("som_sizeof_headers unimplemented"));
5792   abort ();
5793   return 0;
5794 }
5795 
5796 /* Return the single-character symbol type corresponding to
5797    SOM section S, or '?' for an unknown SOM section.  */
5798 
5799 static char
5800 som_section_type (const char *s)
5801 {
5802   const struct section_to_type *t;
5803 
5804   for (t = &stt[0]; t->section; t++)
5805     if (!strcmp (s, t->section))
5806       return t->type;
5807   return '?';
5808 }
5809 
5810 static int
5811 som_decode_symclass (asymbol *symbol)
5812 {
5813   char c;
5814 
5815   if (bfd_is_com_section (symbol->section))
5816     return 'C';
5817   if (bfd_is_und_section (symbol->section))
5818     {
5819       if (symbol->flags & BSF_WEAK)
5820 	{
5821 	  /* If weak, determine if it's specifically an object
5822 	     or non-object weak.  */
5823 	  if (symbol->flags & BSF_OBJECT)
5824 	    return 'v';
5825 	  else
5826 	    return 'w';
5827 	}
5828       else
5829 	 return 'U';
5830     }
5831   if (bfd_is_ind_section (symbol->section))
5832     return 'I';
5833   if (symbol->flags & BSF_WEAK)
5834     {
5835       /* If weak, determine if it's specifically an object
5836 	 or non-object weak.  */
5837       if (symbol->flags & BSF_OBJECT)
5838 	return 'V';
5839       else
5840 	return 'W';
5841     }
5842   if (!(symbol->flags & (BSF_GLOBAL | BSF_LOCAL)))
5843     return '?';
5844 
5845   if (bfd_is_abs_section (symbol->section)
5846       || (som_symbol_data (symbol) != NULL
5847 	  && som_symbol_data (symbol)->som_type == SYMBOL_TYPE_ABSOLUTE))
5848     c = 'a';
5849   else if (symbol->section)
5850     c = som_section_type (symbol->section->name);
5851   else
5852     return '?';
5853   if (symbol->flags & BSF_GLOBAL)
5854     c = TOUPPER (c);
5855   return c;
5856 }
5857 
5858 /* Return information about SOM symbol SYMBOL in RET.  */
5859 
5860 static void
5861 som_get_symbol_info (bfd *ignore_abfd ATTRIBUTE_UNUSED,
5862 		     asymbol *symbol,
5863 		     symbol_info *ret)
5864 {
5865   ret->type = som_decode_symclass (symbol);
5866   if (ret->type != 'U')
5867     ret->value = symbol->value + symbol->section->vma;
5868   else
5869     ret->value = 0;
5870   ret->name = symbol->name;
5871 }
5872 
5873 /* Count the number of symbols in the archive symbol table.  Necessary
5874    so that we can allocate space for all the carsyms at once.  */
5875 
5876 static bfd_boolean
5877 som_bfd_count_ar_symbols (bfd *abfd,
5878 			  struct som_lst_header *lst_header,
5879 			  symindex *count)
5880 {
5881   unsigned int i;
5882   unsigned char *hash_table;
5883   bfd_size_type amt;
5884   file_ptr lst_filepos;
5885 
5886   lst_filepos = bfd_tell (abfd) - sizeof (struct som_external_lst_header);
5887 
5888   hash_table = bfd_malloc2 (lst_header->hash_size, 4);
5889   if (hash_table == NULL && lst_header->hash_size != 0)
5890     goto error_return;
5891 
5892   /* Don't forget to initialize the counter!  */
5893   *count = 0;
5894 
5895   /* Read in the hash table.  The hash table is an array of 32-bit
5896      file offsets which point to the hash chains.  */
5897   amt = (bfd_size_type) lst_header->hash_size * 4;
5898   if (bfd_bread ((void *) hash_table, amt, abfd) != amt)
5899     goto error_return;
5900 
5901   /* Walk each chain counting the number of symbols found on that particular
5902      chain.  */
5903   for (i = 0; i < lst_header->hash_size; i++)
5904     {
5905       struct som_external_lst_symbol_record ext_lst_symbol;
5906       unsigned int hash_val = bfd_getb32 (hash_table + 4 * i);
5907 
5908       /* An empty chain has zero as it's file offset.  */
5909       if (hash_val == 0)
5910 	continue;
5911 
5912       /* Seek to the first symbol in this hash chain.  */
5913       if (bfd_seek (abfd, lst_filepos + hash_val, SEEK_SET) != 0)
5914 	goto error_return;
5915 
5916       /* Read in this symbol and update the counter.  */
5917       amt = sizeof (ext_lst_symbol);
5918       if (bfd_bread ((void *) &ext_lst_symbol, amt, abfd) != amt)
5919 	goto error_return;
5920 
5921       (*count)++;
5922 
5923       /* Now iterate through the rest of the symbols on this chain.  */
5924       while (1)
5925 	{
5926 	  unsigned int next_entry = bfd_getb32 (ext_lst_symbol.next_entry);
5927 
5928 	  if (next_entry == 0)
5929 	    break;
5930 
5931 	  /* Assume symbols on a chain are in increasing file offset
5932 	     order.  Otherwise we can loop here with fuzzed input.  */
5933 	  if (next_entry < hash_val + sizeof (ext_lst_symbol))
5934 	    {
5935 	      bfd_set_error (bfd_error_bad_value);
5936 	      goto error_return;
5937 	    }
5938 	  hash_val = next_entry;
5939 
5940 	  /* Seek to the next symbol.  */
5941 	  if (bfd_seek (abfd, lst_filepos + next_entry, SEEK_SET) != 0)
5942 	    goto error_return;
5943 
5944 	  /* Read the symbol in and update the counter.  */
5945 	  amt = sizeof (ext_lst_symbol);
5946 	  if (bfd_bread ((void *) &ext_lst_symbol, amt, abfd) != amt)
5947 	    goto error_return;
5948 
5949 	  (*count)++;
5950 	}
5951     }
5952   if (hash_table != NULL)
5953     free (hash_table);
5954   return TRUE;
5955 
5956  error_return:
5957   if (hash_table != NULL)
5958     free (hash_table);
5959   return FALSE;
5960 }
5961 
5962 /* Fill in the canonical archive symbols (SYMS) from the archive described
5963    by ABFD and LST_HEADER.  */
5964 
5965 static bfd_boolean
5966 som_bfd_fill_in_ar_symbols (bfd *abfd,
5967 			    struct som_lst_header *lst_header,
5968 			    carsym **syms)
5969 {
5970   unsigned int i;
5971   carsym *set = syms[0];
5972   unsigned char *hash_table;
5973   struct som_external_som_entry *som_dict = NULL;
5974   bfd_size_type amt;
5975   file_ptr lst_filepos;
5976   unsigned int string_loc;
5977 
5978   lst_filepos = bfd_tell (abfd) - sizeof (struct som_external_lst_header);
5979   hash_table = bfd_malloc2 (lst_header->hash_size, 4);
5980   if (hash_table == NULL && lst_header->hash_size != 0)
5981     goto error_return;
5982 
5983   /* Read in the hash table.  The has table is an array of 32bit file offsets
5984      which point to the hash chains.  */
5985   amt = (bfd_size_type) lst_header->hash_size * 4;
5986   if (bfd_bread ((void *) hash_table, amt, abfd) != amt)
5987     goto error_return;
5988 
5989   /* Seek to and read in the SOM dictionary.  We will need this to fill
5990      in the carsym's filepos field.  */
5991   if (bfd_seek (abfd, lst_filepos + lst_header->dir_loc, SEEK_SET) != 0)
5992     goto error_return;
5993 
5994   som_dict = bfd_malloc2 (lst_header->module_count,
5995 			  sizeof (struct som_external_som_entry));
5996   if (som_dict == NULL && lst_header->module_count != 0)
5997     goto error_return;
5998 
5999   amt = lst_header->module_count;
6000   amt *= sizeof (struct som_external_som_entry);
6001   if (bfd_bread ((void *) som_dict, amt, abfd) != amt)
6002     goto error_return;
6003 
6004   string_loc = lst_header->string_loc;
6005 
6006   /* Walk each chain filling in the carsyms as we go along.  */
6007   for (i = 0; i < lst_header->hash_size; i++)
6008     {
6009       struct som_external_lst_symbol_record lst_symbol;
6010       unsigned int hash_val;
6011       size_t len;
6012       unsigned char ext_len[4];
6013       char *name;
6014       unsigned int ndx;
6015 
6016       /* An empty chain has zero as it's file offset.  */
6017       hash_val = bfd_getb32 (hash_table + 4 * i);
6018       if (hash_val == 0)
6019 	continue;
6020 
6021       /* Seek to and read the first symbol on the chain.  */
6022       if (bfd_seek (abfd, lst_filepos + hash_val, SEEK_SET) != 0)
6023 	goto error_return;
6024 
6025       amt = sizeof (lst_symbol);
6026       if (bfd_bread ((void *) &lst_symbol, amt, abfd) != amt)
6027 	goto error_return;
6028 
6029       /* Get the name of the symbol, first get the length which is stored
6030 	 as a 32bit integer just before the symbol.
6031 
6032 	 One might ask why we don't just read in the entire string table
6033 	 and index into it.  Well, according to the SOM ABI the string
6034 	 index can point *anywhere* in the archive to save space, so just
6035 	 using the string table would not be safe.  */
6036       if (bfd_seek (abfd, (lst_filepos + string_loc
6037 			   + bfd_getb32 (lst_symbol.name) - 4), SEEK_SET) != 0)
6038 	goto error_return;
6039 
6040       if (bfd_bread (&ext_len, (bfd_size_type) 4, abfd) != 4)
6041 	goto error_return;
6042       len = bfd_getb32 (ext_len);
6043 
6044       /* Allocate space for the name and null terminate it too.  */
6045       if (len == (size_t) -1)
6046 	{
6047 	  bfd_set_error (bfd_error_no_memory);
6048 	  goto error_return;
6049 	}
6050       name = bfd_zalloc (abfd, (bfd_size_type) len + 1);
6051       if (!name)
6052 	goto error_return;
6053       if (bfd_bread (name, (bfd_size_type) len, abfd) != len)
6054 	goto error_return;
6055 
6056       name[len] = 0;
6057       set->name = name;
6058 
6059       /* Fill in the file offset.  Note that the "location" field points
6060 	 to the SOM itself, not the ar_hdr in front of it.  */
6061       ndx = bfd_getb32 (lst_symbol.som_index);
6062       if (ndx >= lst_header->module_count)
6063 	{
6064 	  bfd_set_error (bfd_error_bad_value);
6065 	  goto error_return;
6066 	}
6067       set->file_offset
6068 	= bfd_getb32 (som_dict[ndx].location) - sizeof (struct ar_hdr);
6069 
6070       /* Go to the next symbol.  */
6071       set++;
6072 
6073       /* Iterate through the rest of the chain.  */
6074       while (1)
6075 	{
6076 	  unsigned int next_entry = bfd_getb32 (lst_symbol.next_entry);
6077 
6078 	  if (next_entry == 0)
6079 	    break;
6080 
6081 	  /* Seek to the next symbol and read it in.  */
6082 	  if (bfd_seek (abfd, lst_filepos + next_entry, SEEK_SET) != 0)
6083 	    goto error_return;
6084 
6085 	  amt = sizeof (lst_symbol);
6086 	  if (bfd_bread ((void *) &lst_symbol, amt, abfd) != amt)
6087 	    goto error_return;
6088 
6089 	  /* Seek to the name length & string and read them in.  */
6090 	  if (bfd_seek (abfd, lst_filepos + string_loc
6091 			+ bfd_getb32 (lst_symbol.name) - 4, SEEK_SET) != 0)
6092 	    goto error_return;
6093 
6094 	  if (bfd_bread (&ext_len, (bfd_size_type) 4, abfd) != 4)
6095 	    goto error_return;
6096 	  len = bfd_getb32 (ext_len);
6097 
6098 	  /* Allocate space for the name and null terminate it too.  */
6099 	  if (len == (size_t) -1)
6100 	    {
6101 	      bfd_set_error (bfd_error_no_memory);
6102 	      goto error_return;
6103 	    }
6104 	  name = bfd_zalloc (abfd, (bfd_size_type) len + 1);
6105 	  if (!name)
6106 	    goto error_return;
6107 
6108 	  if (bfd_bread (name, (bfd_size_type) len, abfd) != len)
6109 	    goto error_return;
6110 	  name[len] = 0;
6111 	  set->name = name;
6112 
6113 	  /* Fill in the file offset.  Note that the "location" field points
6114 	     to the SOM itself, not the ar_hdr in front of it.  */
6115 	  ndx = bfd_getb32 (lst_symbol.som_index);
6116 	  if (ndx >= lst_header->module_count)
6117 	    {
6118 	      bfd_set_error (bfd_error_bad_value);
6119 	      goto error_return;
6120 	    }
6121 	  set->file_offset
6122 	    = bfd_getb32 (som_dict[ndx].location) - sizeof (struct ar_hdr);
6123 
6124 	  /* Go on to the next symbol.  */
6125 	  set++;
6126 	}
6127     }
6128   /* If we haven't died by now, then we successfully read the entire
6129      archive symbol table.  */
6130   if (hash_table != NULL)
6131     free (hash_table);
6132   if (som_dict != NULL)
6133     free (som_dict);
6134   return TRUE;
6135 
6136  error_return:
6137   if (hash_table != NULL)
6138     free (hash_table);
6139   if (som_dict != NULL)
6140     free (som_dict);
6141   return FALSE;
6142 }
6143 
6144 /* Read in the LST from the archive.  */
6145 
6146 static bfd_boolean
6147 som_slurp_armap (bfd *abfd)
6148 {
6149   struct som_external_lst_header ext_lst_header;
6150   struct som_lst_header lst_header;
6151   struct ar_hdr ar_header;
6152   unsigned int parsed_size;
6153   struct artdata *ardata = bfd_ardata (abfd);
6154   char nextname[17];
6155   bfd_size_type amt = 16;
6156   int i = bfd_bread ((void *) nextname, amt, abfd);
6157 
6158   /* Special cases.  */
6159   if (i == 0)
6160     return TRUE;
6161   if (i != 16)
6162     return FALSE;
6163 
6164   if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
6165     return FALSE;
6166 
6167   /* For archives without .o files there is no symbol table.  */
6168   if (! CONST_STRNEQ (nextname, "/               "))
6169     {
6170       abfd->has_armap = FALSE;
6171       return TRUE;
6172     }
6173 
6174   /* Read in and sanity check the archive header.  */
6175   amt = sizeof (struct ar_hdr);
6176   if (bfd_bread ((void *) &ar_header, amt, abfd) != amt)
6177     return FALSE;
6178 
6179   if (strncmp (ar_header.ar_fmag, ARFMAG, 2))
6180     {
6181       bfd_set_error (bfd_error_malformed_archive);
6182       return FALSE;
6183     }
6184 
6185   /* How big is the archive symbol table entry?  */
6186   errno = 0;
6187   parsed_size = strtol (ar_header.ar_size, NULL, 10);
6188   if (errno != 0)
6189     {
6190       bfd_set_error (bfd_error_malformed_archive);
6191       return FALSE;
6192     }
6193 
6194   /* Save off the file offset of the first real user data.  */
6195   ardata->first_file_filepos = bfd_tell (abfd) + parsed_size;
6196 
6197   /* Read in the library symbol table.  We'll make heavy use of this
6198      in just a minute.  */
6199   amt = sizeof (struct som_external_lst_header);
6200   if (bfd_bread ((void *) &ext_lst_header, amt, abfd) != amt)
6201     return FALSE;
6202 
6203   som_swap_lst_header_in (&ext_lst_header, &lst_header);
6204 
6205   /* Sanity check.  */
6206   if (lst_header.a_magic != LIBMAGIC)
6207     {
6208       bfd_set_error (bfd_error_malformed_archive);
6209       return FALSE;
6210     }
6211 
6212   /* Count the number of symbols in the library symbol table.  */
6213   if (! som_bfd_count_ar_symbols (abfd, &lst_header, &ardata->symdef_count))
6214     return FALSE;
6215 
6216   /* Get back to the start of the library symbol table.  */
6217   if (bfd_seek (abfd, (ardata->first_file_filepos - parsed_size
6218 		       + sizeof (struct som_external_lst_header)),
6219 		SEEK_SET) != 0)
6220     return FALSE;
6221 
6222   /* Initialize the cache and allocate space for the library symbols.  */
6223   ardata->cache = 0;
6224   ardata->symdefs = bfd_alloc2 (abfd, ardata->symdef_count, sizeof (carsym));
6225   if (!ardata->symdefs)
6226     return FALSE;
6227 
6228   /* Now fill in the canonical archive symbols.  */
6229   if (! som_bfd_fill_in_ar_symbols (abfd, &lst_header, &ardata->symdefs))
6230     return FALSE;
6231 
6232   /* Seek back to the "first" file in the archive.  Note the "first"
6233      file may be the extended name table.  */
6234   if (bfd_seek (abfd, ardata->first_file_filepos, SEEK_SET) != 0)
6235     return FALSE;
6236 
6237   /* Notify the generic archive code that we have a symbol map.  */
6238   abfd->has_armap = TRUE;
6239   return TRUE;
6240 }
6241 
6242 /* Begin preparing to write a SOM library symbol table.
6243 
6244    As part of the prep work we need to determine the number of symbols
6245    and the size of the associated string section.  */
6246 
6247 static bfd_boolean
6248 som_bfd_prep_for_ar_write (bfd *abfd,
6249 			   unsigned int *num_syms,
6250 			   unsigned int *stringsize)
6251 {
6252   bfd *curr_bfd = abfd->archive_head;
6253 
6254   /* Some initialization.  */
6255   *num_syms = 0;
6256   *stringsize = 0;
6257 
6258   /* Iterate over each BFD within this archive.  */
6259   while (curr_bfd != NULL)
6260     {
6261       unsigned int curr_count, i;
6262       som_symbol_type *sym;
6263 
6264       /* Don't bother for non-SOM objects.  */
6265       if (curr_bfd->format != bfd_object
6266 	  || curr_bfd->xvec->flavour != bfd_target_som_flavour)
6267 	{
6268 	  curr_bfd = curr_bfd->archive_next;
6269 	  continue;
6270 	}
6271 
6272       /* Make sure the symbol table has been read, then snag a pointer
6273 	 to it.  It's a little slimey to grab the symbols via obj_som_symtab,
6274 	 but doing so avoids allocating lots of extra memory.  */
6275       if (! som_slurp_symbol_table (curr_bfd))
6276 	return FALSE;
6277 
6278       sym = obj_som_symtab (curr_bfd);
6279       curr_count = bfd_get_symcount (curr_bfd);
6280 
6281       /* Examine each symbol to determine if it belongs in the
6282 	 library symbol table.  */
6283       for (i = 0; i < curr_count; i++, sym++)
6284 	{
6285 	  struct som_misc_symbol_info info;
6286 
6287 	  /* Derive SOM information from the BFD symbol.  */
6288 	  som_bfd_derive_misc_symbol_info (curr_bfd, &sym->symbol, &info);
6289 
6290 	  /* Should we include this symbol?  */
6291 	  if (info.symbol_type == ST_NULL
6292 	      || info.symbol_type == ST_SYM_EXT
6293 	      || info.symbol_type == ST_ARG_EXT)
6294 	    continue;
6295 
6296 	  /* Only global symbols and unsatisfied commons.  */
6297 	  if (info.symbol_scope != SS_UNIVERSAL
6298 	      && info.symbol_type != ST_STORAGE)
6299 	    continue;
6300 
6301 	  /* Do no include undefined symbols.  */
6302 	  if (bfd_is_und_section (sym->symbol.section))
6303 	    continue;
6304 
6305 	  /* Bump the various counters, being careful to honor
6306 	     alignment considerations in the string table.  */
6307 	  (*num_syms)++;
6308 	  *stringsize += strlen (sym->symbol.name) + 5;
6309 	  while (*stringsize % 4)
6310 	    (*stringsize)++;
6311 	}
6312 
6313       curr_bfd = curr_bfd->archive_next;
6314     }
6315   return TRUE;
6316 }
6317 
6318 /* Hash a symbol name based on the hashing algorithm presented in the
6319    SOM ABI.  */
6320 
6321 static unsigned int
6322 som_bfd_ar_symbol_hash (asymbol *symbol)
6323 {
6324   unsigned int len = strlen (symbol->name);
6325 
6326   /* Names with length 1 are special.  */
6327   if (len == 1)
6328     return 0x1000100 | (symbol->name[0] << 16) | symbol->name[0];
6329 
6330   return ((len & 0x7f) << 24) | (symbol->name[1] << 16)
6331 	  | (symbol->name[len - 2] << 8) | symbol->name[len - 1];
6332 }
6333 
6334 /* Do the bulk of the work required to write the SOM library
6335    symbol table.  */
6336 
6337 static bfd_boolean
6338 som_bfd_ar_write_symbol_stuff (bfd *abfd,
6339 			       unsigned int nsyms,
6340 			       unsigned int string_size,
6341 			       struct som_external_lst_header lst,
6342 			       unsigned elength)
6343 {
6344   char *strings = NULL, *p;
6345   struct som_external_lst_symbol_record *lst_syms = NULL, *curr_lst_sym;
6346   bfd *curr_bfd;
6347   unsigned char *hash_table = NULL;
6348   struct som_external_som_entry *som_dict = NULL;
6349   struct som_external_lst_symbol_record **last_hash_entry = NULL;
6350   unsigned int curr_som_offset, som_index = 0;
6351   bfd_size_type amt;
6352   unsigned int module_count;
6353   unsigned int hash_size;
6354 
6355   hash_size = bfd_getb32 (lst.hash_size);
6356   hash_table = bfd_zmalloc2 (hash_size, 4);
6357   if (hash_table == NULL && hash_size != 0)
6358     goto error_return;
6359 
6360   module_count = bfd_getb32 (lst.module_count);
6361   som_dict = bfd_zmalloc2 (module_count, sizeof (struct som_external_som_entry));
6362   if (som_dict == NULL && module_count != 0)
6363     goto error_return;
6364 
6365   last_hash_entry
6366     = bfd_zmalloc2 (hash_size, sizeof (struct som_external_lst_symbol_record *));
6367   if (last_hash_entry == NULL && hash_size != 0)
6368     goto error_return;
6369 
6370   /* Symbols have som_index fields, so we have to keep track of the
6371      index of each SOM in the archive.
6372 
6373      The SOM dictionary has (among other things) the absolute file
6374      position for the SOM which a particular dictionary entry
6375      describes.  We have to compute that information as we iterate
6376      through the SOMs/symbols.  */
6377   som_index = 0;
6378 
6379   /* We add in the size of the archive header twice as the location
6380      in the SOM dictionary is the actual offset of the SOM, not the
6381      archive header before the SOM.  */
6382   curr_som_offset = 8 + 2 * sizeof (struct ar_hdr) + bfd_getb32 (lst.file_end);
6383 
6384   /* Make room for the archive header and the contents of the
6385      extended string table.  Note that elength includes the size
6386      of the archive header for the extended name table!  */
6387   if (elength)
6388     curr_som_offset += elength;
6389 
6390   /* Make sure we're properly aligned.  */
6391   curr_som_offset = (curr_som_offset + 0x1) & ~0x1;
6392 
6393   /* FIXME should be done with buffers just like everything else...  */
6394   lst_syms = bfd_malloc2 (nsyms, sizeof (struct som_external_lst_symbol_record));
6395   if (lst_syms == NULL && nsyms != 0)
6396     goto error_return;
6397   strings = bfd_malloc ((bfd_size_type) string_size);
6398   if (strings == NULL && string_size != 0)
6399     goto error_return;
6400 
6401   p = strings;
6402   curr_lst_sym = lst_syms;
6403 
6404   curr_bfd = abfd->archive_head;
6405   while (curr_bfd != NULL)
6406     {
6407       unsigned int curr_count, i;
6408       som_symbol_type *sym;
6409 
6410       /* Don't bother for non-SOM objects.  */
6411       if (curr_bfd->format != bfd_object
6412 	  || curr_bfd->xvec->flavour != bfd_target_som_flavour)
6413 	{
6414 	  curr_bfd = curr_bfd->archive_next;
6415 	  continue;
6416 	}
6417 
6418       /* Make sure the symbol table has been read, then snag a pointer
6419 	 to it.  It's a little slimey to grab the symbols via obj_som_symtab,
6420 	 but doing so avoids allocating lots of extra memory.  */
6421       if (! som_slurp_symbol_table (curr_bfd))
6422 	goto error_return;
6423 
6424       sym = obj_som_symtab (curr_bfd);
6425       curr_count = bfd_get_symcount (curr_bfd);
6426 
6427       for (i = 0; i < curr_count; i++, sym++)
6428 	{
6429 	  struct som_misc_symbol_info info;
6430 	  struct som_external_lst_symbol_record *last;
6431 	  unsigned int symbol_pos;
6432 	  unsigned int slen;
6433 	  unsigned int symbol_key;
6434 	  unsigned int flags;
6435 
6436 	  /* Derive SOM information from the BFD symbol.  */
6437 	  som_bfd_derive_misc_symbol_info (curr_bfd, &sym->symbol, &info);
6438 
6439 	  /* Should we include this symbol?  */
6440 	  if (info.symbol_type == ST_NULL
6441 	      || info.symbol_type == ST_SYM_EXT
6442 	      || info.symbol_type == ST_ARG_EXT)
6443 	    continue;
6444 
6445 	  /* Only global symbols and unsatisfied commons.  */
6446 	  if (info.symbol_scope != SS_UNIVERSAL
6447 	      && info.symbol_type != ST_STORAGE)
6448 	    continue;
6449 
6450 	  /* Do no include undefined symbols.  */
6451 	  if (bfd_is_und_section (sym->symbol.section))
6452 	    continue;
6453 
6454 	  /* If this is the first symbol from this SOM, then update
6455 	     the SOM dictionary too.  */
6456 	  if (bfd_getb32 (som_dict[som_index].location) == 0)
6457 	    {
6458 	      bfd_putb32 (curr_som_offset, som_dict[som_index].location);
6459 	      bfd_putb32 (arelt_size (curr_bfd), som_dict[som_index].length);
6460 	    }
6461 
6462 	  symbol_key = som_bfd_ar_symbol_hash (&sym->symbol);
6463 
6464 	  /* Fill in the lst symbol record.  */
6465 	  flags = 0;
6466 	  if (info.secondary_def)
6467 	    flags |= LST_SYMBOL_SECONDARY_DEF;
6468 	  flags |= info.symbol_type << LST_SYMBOL_SYMBOL_TYPE_SH;
6469 	  flags |= info.symbol_scope << LST_SYMBOL_SYMBOL_SCOPE_SH;
6470 	  if (bfd_is_com_section (sym->symbol.section))
6471 	    flags |= LST_SYMBOL_IS_COMMON;
6472 	  if (info.dup_common)
6473 	    flags |= LST_SYMBOL_DUP_COMMON;
6474 	  flags |= 3 << LST_SYMBOL_XLEAST_SH;
6475 	  flags |= info.arg_reloc << LST_SYMBOL_ARG_RELOC_SH;
6476 	  bfd_putb32 (flags, curr_lst_sym->flags);
6477 	  bfd_putb32 (p - strings + 4, curr_lst_sym->name);
6478 	  bfd_putb32 (0, curr_lst_sym->qualifier_name);
6479 	  bfd_putb32 (info.symbol_info, curr_lst_sym->symbol_info);
6480 	  bfd_putb32 (info.symbol_value | info.priv_level,
6481 		      curr_lst_sym->symbol_value);
6482 	  bfd_putb32 (0, curr_lst_sym->symbol_descriptor);
6483 	  curr_lst_sym->reserved = 0;
6484 	  bfd_putb32 (som_index, curr_lst_sym->som_index);
6485 	  bfd_putb32 (symbol_key, curr_lst_sym->symbol_key);
6486 	  bfd_putb32 (0, curr_lst_sym->next_entry);
6487 
6488 	  /* Insert into the hash table.  */
6489 	  symbol_pos =
6490 	    (curr_lst_sym - lst_syms)
6491 	    * sizeof (struct som_external_lst_symbol_record)
6492 	    + hash_size * 4
6493 	    + module_count * sizeof (struct som_external_som_entry)
6494 	    + sizeof (struct som_external_lst_header);
6495 	  last = last_hash_entry[symbol_key % hash_size];
6496 	  if (last != NULL)
6497 	    {
6498 	      /* There is already something at the head of this hash chain,
6499 		 so tack this symbol onto the end of the chain.  */
6500 	      bfd_putb32 (symbol_pos, last->next_entry);
6501 	    }
6502 	  else
6503 	    /* First entry in this hash chain.  */
6504 	    bfd_putb32 (symbol_pos, hash_table + 4 * (symbol_key % hash_size));
6505 
6506 	  /* Keep track of the last symbol we added to this chain so we can
6507 	     easily update its next_entry pointer.  */
6508 	  last_hash_entry[symbol_key % hash_size] = curr_lst_sym;
6509 
6510 	  /* Update the string table.  */
6511 	  slen = strlen (sym->symbol.name);
6512 	  bfd_put_32 (abfd, slen, p);
6513 	  p += 4;
6514 	  slen++; /* Nul terminator.  */
6515 	  memcpy (p, sym->symbol.name, slen);
6516 	  p += slen;
6517 	  while (slen % 4)
6518 	    {
6519 	      bfd_put_8 (abfd, 0, p);
6520 	      p++;
6521 	      slen++;
6522 	    }
6523 	  BFD_ASSERT (p <= strings + string_size);
6524 
6525 	  /* Head to the next symbol.  */
6526 	  curr_lst_sym++;
6527 	}
6528 
6529       /* Keep track of where each SOM will finally reside; then look
6530 	 at the next BFD.  */
6531       curr_som_offset += arelt_size (curr_bfd) + sizeof (struct ar_hdr);
6532 
6533       /* A particular object in the archive may have an odd length; the
6534 	 linker requires objects begin on an even boundary.  So round
6535 	 up the current offset as necessary.  */
6536       curr_som_offset = (curr_som_offset + 0x1) &~ (unsigned) 1;
6537       curr_bfd = curr_bfd->archive_next;
6538       som_index++;
6539     }
6540 
6541   /* Now scribble out the hash table.  */
6542   amt = (bfd_size_type) hash_size * 4;
6543   if (bfd_bwrite ((void *) hash_table, amt, abfd) != amt)
6544     goto error_return;
6545 
6546   /* Then the SOM dictionary.  */
6547   amt = (bfd_size_type) module_count * sizeof (struct som_external_som_entry);
6548   if (bfd_bwrite ((void *) som_dict, amt, abfd) != amt)
6549     goto error_return;
6550 
6551   /* The library symbols.  */
6552   amt = (bfd_size_type) nsyms * sizeof (struct som_external_lst_symbol_record);
6553   if (bfd_bwrite ((void *) lst_syms, amt, abfd) != amt)
6554     goto error_return;
6555 
6556   /* And finally the strings.  */
6557   amt = string_size;
6558   if (bfd_bwrite ((void *) strings, amt, abfd) != amt)
6559     goto error_return;
6560 
6561   if (hash_table != NULL)
6562     free (hash_table);
6563   if (som_dict != NULL)
6564     free (som_dict);
6565   if (last_hash_entry != NULL)
6566     free (last_hash_entry);
6567   if (lst_syms != NULL)
6568     free (lst_syms);
6569   if (strings != NULL)
6570     free (strings);
6571   return TRUE;
6572 
6573  error_return:
6574   if (hash_table != NULL)
6575     free (hash_table);
6576   if (som_dict != NULL)
6577     free (som_dict);
6578   if (last_hash_entry != NULL)
6579     free (last_hash_entry);
6580   if (lst_syms != NULL)
6581     free (lst_syms);
6582   if (strings != NULL)
6583     free (strings);
6584 
6585   return FALSE;
6586 }
6587 
6588 /* Write out the LST for the archive.
6589 
6590    You'll never believe this is really how armaps are handled in SOM...  */
6591 
6592 static bfd_boolean
6593 som_write_armap (bfd *abfd,
6594 		 unsigned int elength,
6595 		 struct orl *map ATTRIBUTE_UNUSED,
6596 		 unsigned int orl_count ATTRIBUTE_UNUSED,
6597 		 int stridx ATTRIBUTE_UNUSED)
6598 {
6599   bfd *curr_bfd;
6600   struct stat statbuf;
6601   unsigned int i, lst_size, nsyms, stringsize;
6602   struct ar_hdr hdr;
6603   struct som_external_lst_header lst;
6604   unsigned char *p;
6605   bfd_size_type amt;
6606   unsigned int csum;
6607   unsigned int module_count;
6608 
6609   /* We'll use this for the archive's date and mode later.  */
6610   if (stat (abfd->filename, &statbuf) != 0)
6611     {
6612       bfd_set_error (bfd_error_system_call);
6613       return FALSE;
6614     }
6615   /* Fudge factor.  */
6616   bfd_ardata (abfd)->armap_timestamp = statbuf.st_mtime + 60;
6617 
6618   /* Account for the lst header first.  */
6619   lst_size = sizeof (struct som_external_lst_header);
6620 
6621   /* Start building the LST header.  */
6622   /* FIXME:  Do we need to examine each element to determine the
6623      largest id number?  */
6624   bfd_putb16 (CPU_PA_RISC1_0, &lst.system_id);
6625   bfd_putb16 (LIBMAGIC, &lst.a_magic);
6626   bfd_putb32 (VERSION_ID, &lst.version_id);
6627   bfd_putb32 (0, &lst.file_time.secs);
6628   bfd_putb32 (0, &lst.file_time.nanosecs);
6629 
6630   bfd_putb32 (lst_size, &lst.hash_loc);
6631   bfd_putb32 (SOM_LST_HASH_SIZE, &lst.hash_size);
6632 
6633   /* Hash table is a SOM_LST_HASH_SIZE 32bit offsets.  */
6634   lst_size += 4 * SOM_LST_HASH_SIZE;
6635 
6636   /* We need to count the number of SOMs in this archive.  */
6637   curr_bfd = abfd->archive_head;
6638   module_count = 0;
6639   while (curr_bfd != NULL)
6640     {
6641       /* Only true SOM objects count.  */
6642       if (curr_bfd->format == bfd_object
6643 	  && curr_bfd->xvec->flavour == bfd_target_som_flavour)
6644 	module_count++;
6645       curr_bfd = curr_bfd->archive_next;
6646     }
6647   bfd_putb32 (module_count, &lst.module_count);
6648   bfd_putb32 (module_count, &lst.module_limit);
6649   bfd_putb32 (lst_size, &lst.dir_loc);
6650   lst_size += sizeof (struct som_external_som_entry) * module_count;
6651 
6652   /* We don't support import/export tables, auxiliary headers,
6653      or free lists yet.  Make the linker work a little harder
6654      to make our life easier.  */
6655 
6656   bfd_putb32 (0, &lst.export_loc);
6657   bfd_putb32 (0, &lst.export_count);
6658   bfd_putb32 (0, &lst.import_loc);
6659   bfd_putb32 (0, &lst.aux_loc);
6660   bfd_putb32 (0, &lst.aux_size);
6661 
6662   /* Count how many symbols we will have on the hash chains and the
6663      size of the associated string table.  */
6664   if (! som_bfd_prep_for_ar_write (abfd, &nsyms, &stringsize))
6665     return FALSE;
6666 
6667   lst_size += sizeof (struct som_external_lst_symbol_record) * nsyms;
6668 
6669   /* For the string table.  One day we might actually use this info
6670      to avoid small seeks/reads when reading archives.  */
6671   bfd_putb32 (lst_size, &lst.string_loc);
6672   bfd_putb32 (stringsize, &lst.string_size);
6673   lst_size += stringsize;
6674 
6675   /* SOM ABI says this must be zero.  */
6676   bfd_putb32 (0, &lst.free_list);
6677   bfd_putb32 (lst_size, &lst.file_end);
6678 
6679   /* Compute the checksum.  Must happen after the entire lst header
6680      has filled in.  */
6681   p = (unsigned char *) &lst;
6682   csum = 0;
6683   for (i = 0; i < sizeof (struct som_external_lst_header) - sizeof (int);
6684        i += 4)
6685     csum ^= bfd_getb32 (&p[i]);
6686   bfd_putb32 (csum, &lst.checksum);
6687 
6688   sprintf (hdr.ar_name, "/              ");
6689   _bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%-12ld",
6690 		    bfd_ardata (abfd)->armap_timestamp);
6691   _bfd_ar_spacepad (hdr.ar_uid, sizeof (hdr.ar_uid), "%ld",
6692 		    statbuf.st_uid);
6693   _bfd_ar_spacepad (hdr.ar_gid, sizeof (hdr.ar_gid), "%ld",
6694 		    statbuf.st_gid);
6695   _bfd_ar_spacepad (hdr.ar_mode, sizeof (hdr.ar_mode), "%-8o",
6696 		    (unsigned int)statbuf.st_mode);
6697   _bfd_ar_spacepad (hdr.ar_size, sizeof (hdr.ar_size), "%-10d",
6698 		    (int) lst_size);
6699   hdr.ar_fmag[0] = '`';
6700   hdr.ar_fmag[1] = '\012';
6701 
6702   /* Turn any nulls into spaces.  */
6703   for (i = 0; i < sizeof (struct ar_hdr); i++)
6704     if (((char *) (&hdr))[i] == '\0')
6705       (((char *) (&hdr))[i]) = ' ';
6706 
6707   /* Scribble out the ar header.  */
6708   amt = sizeof (struct ar_hdr);
6709   if (bfd_bwrite ((void *) &hdr, amt, abfd) != amt)
6710     return FALSE;
6711 
6712   /* Now scribble out the lst header.  */
6713   amt = sizeof (struct som_external_lst_header);
6714   if (bfd_bwrite ((void *) &lst, amt, abfd) != amt)
6715     return FALSE;
6716 
6717   /* Build and write the armap.  */
6718   if (!som_bfd_ar_write_symbol_stuff (abfd, nsyms, stringsize, lst, elength))
6719     return FALSE;
6720 
6721   /* Done.  */
6722   return TRUE;
6723 }
6724 
6725 /* Free all information we have cached for this BFD.  We can always
6726    read it again later if we need it.  */
6727 
6728 static bfd_boolean
6729 som_bfd_free_cached_info (bfd *abfd)
6730 {
6731   if (bfd_get_format (abfd) == bfd_object)
6732     {
6733       asection *o;
6734 
6735 #define FREE(x) if (x != NULL) { free (x); x = NULL; }
6736       /* Free the native string and symbol tables.  */
6737       FREE (obj_som_symtab (abfd));
6738       FREE (obj_som_stringtab (abfd));
6739       for (o = abfd->sections; o != NULL; o = o->next)
6740 	{
6741 	  /* Free the native relocations.  */
6742 	  o->reloc_count = (unsigned) -1;
6743 	  FREE (som_section_data (o)->reloc_stream);
6744 	  /* Do not free the generic relocations as they are objalloc'ed.  */
6745 	}
6746 #undef FREE
6747     }
6748 
6749   return _bfd_generic_close_and_cleanup (abfd);
6750 }
6751 
6752 /* End of miscellaneous support functions.  */
6753 
6754 /* Linker support functions.  */
6755 
6756 static bfd_boolean
6757 som_bfd_link_split_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
6758 {
6759   return som_is_subspace (sec) && sec->size > 240000;
6760 }
6761 
6762 #define som_find_line				_bfd_nosymbols_find_line
6763 #define som_get_symbol_version_string		_bfd_nosymbols_get_symbol_version_string
6764 #define	som_close_and_cleanup			som_bfd_free_cached_info
6765 #define som_read_ar_hdr				_bfd_generic_read_ar_hdr
6766 #define som_write_ar_hdr			_bfd_generic_write_ar_hdr
6767 #define som_openr_next_archived_file		bfd_generic_openr_next_archived_file
6768 #define som_get_elt_at_index			_bfd_generic_get_elt_at_index
6769 #define som_generic_stat_arch_elt		bfd_generic_stat_arch_elt
6770 #define som_truncate_arname			bfd_bsd_truncate_arname
6771 #define som_slurp_extended_name_table		_bfd_slurp_extended_name_table
6772 #define som_construct_extended_name_table	_bfd_archive_coff_construct_extended_name_table
6773 #define som_update_armap_timestamp		_bfd_bool_bfd_true
6774 #define som_bfd_is_target_special_symbol        _bfd_bool_bfd_asymbol_false
6775 #define som_get_lineno				_bfd_nosymbols_get_lineno
6776 #define som_bfd_make_debug_symbol		_bfd_nosymbols_bfd_make_debug_symbol
6777 #define som_read_minisymbols			_bfd_generic_read_minisymbols
6778 #define som_minisymbol_to_symbol		_bfd_generic_minisymbol_to_symbol
6779 #define som_get_section_contents_in_window	_bfd_generic_get_section_contents_in_window
6780 #define som_bfd_get_relocated_section_contents	bfd_generic_get_relocated_section_contents
6781 #define som_bfd_relax_section			bfd_generic_relax_section
6782 #define som_bfd_link_hash_table_create		_bfd_generic_link_hash_table_create
6783 #define som_bfd_link_add_symbols		_bfd_generic_link_add_symbols
6784 #define som_bfd_link_just_syms			_bfd_generic_link_just_syms
6785 #define som_bfd_copy_link_hash_symbol_type \
6786   _bfd_generic_copy_link_hash_symbol_type
6787 #define som_bfd_final_link			_bfd_generic_final_link
6788 #define som_bfd_gc_sections			bfd_generic_gc_sections
6789 #define som_bfd_lookup_section_flags		bfd_generic_lookup_section_flags
6790 #define som_bfd_merge_sections			bfd_generic_merge_sections
6791 #define som_bfd_is_group_section		bfd_generic_is_group_section
6792 #define som_bfd_group_name			bfd_generic_group_name
6793 #define som_bfd_discard_group			bfd_generic_discard_group
6794 #define som_section_already_linked		_bfd_generic_section_already_linked
6795 #define som_bfd_define_common_symbol		bfd_generic_define_common_symbol
6796 #define som_bfd_link_hide_symbol		_bfd_generic_link_hide_symbol
6797 #define som_bfd_define_start_stop		bfd_generic_define_start_stop
6798 #define som_bfd_merge_private_bfd_data		_bfd_generic_bfd_merge_private_bfd_data
6799 #define som_bfd_copy_private_header_data	_bfd_generic_bfd_copy_private_header_data
6800 #define som_bfd_set_private_flags		_bfd_generic_bfd_set_private_flags
6801 #define som_find_inliner_info			_bfd_nosymbols_find_inliner_info
6802 #define som_bfd_link_check_relocs		_bfd_generic_link_check_relocs
6803 #define som_set_reloc				_bfd_generic_set_reloc
6804 
6805 const bfd_target hppa_som_vec =
6806 {
6807   "som",			/* Name.  */
6808   bfd_target_som_flavour,
6809   BFD_ENDIAN_BIG,		/* Target byte order.  */
6810   BFD_ENDIAN_BIG,		/* Target headers byte order.  */
6811   (HAS_RELOC | EXEC_P |		/* Object flags.  */
6812    HAS_LINENO | HAS_DEBUG |
6813    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED | DYNAMIC),
6814   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS | SEC_LINK_ONCE
6815    | SEC_ALLOC | SEC_LOAD | SEC_RELOC),		/* Section flags.  */
6816 
6817   /* Leading_symbol_char: is the first char of a user symbol
6818      predictable, and if so what is it.  */
6819   0,
6820   '/',				/* AR_pad_char.  */
6821   14,				/* AR_max_namelen.  */
6822   0,				/* match priority.  */
6823   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
6824   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
6825   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Data.  */
6826   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
6827   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
6828   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Headers.  */
6829   {_bfd_dummy_target,
6830    som_object_p,		/* bfd_check_format.  */
6831    bfd_generic_archive_p,
6832    _bfd_dummy_target
6833   },
6834   {
6835     _bfd_bool_bfd_false_error,
6836     som_mkobject,
6837     _bfd_generic_mkarchive,
6838     _bfd_bool_bfd_false_error
6839   },
6840   {
6841     _bfd_bool_bfd_false_error,
6842     som_write_object_contents,
6843     _bfd_write_archive_contents,
6844     _bfd_bool_bfd_false_error,
6845   },
6846 #undef som
6847 
6848   BFD_JUMP_TABLE_GENERIC (som),
6849   BFD_JUMP_TABLE_COPY (som),
6850   BFD_JUMP_TABLE_CORE (_bfd_nocore),
6851   BFD_JUMP_TABLE_ARCHIVE (som),
6852   BFD_JUMP_TABLE_SYMBOLS (som),
6853   BFD_JUMP_TABLE_RELOCS (som),
6854   BFD_JUMP_TABLE_WRITE (som),
6855   BFD_JUMP_TABLE_LINK (som),
6856   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
6857 
6858   NULL,
6859 
6860   NULL
6861 };
6862 
6863