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