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