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