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