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