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