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