Revert last change (never should have been checked in to begin with).
[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
2298   /* Now sort the symbols.  */
2299   qsort (syms, num_syms, sizeof (asymbol *), compare_syms);
2300
2301   /* Compute the symbol indexes, they will be needed by the relocation
2302      code.  */
2303   for (i = 0; i < num_syms; i++)
2304     {
2305       /* A section symbol.  Again, there is no pointer to backend symbol
2306          information, so we reuse (abuse) the udata field again.  */
2307       if (syms[i]->flags & BSF_SECTION_SYM)
2308         syms[i]->udata = (PTR) i;
2309       else
2310         som_symbol_data (syms[i])->index = i;
2311     }
2312 }
2313
2314 static boolean
2315 som_write_fixups (abfd, current_offset, total_reloc_sizep)
2316      bfd *abfd;
2317      unsigned long current_offset;
2318      unsigned int *total_reloc_sizep;
2319 {
2320   unsigned int i, j;
2321   /* Chunk of memory that we can use as buffer space, then throw
2322      away.  */
2323   unsigned char tmp_space[SOM_TMP_BUFSIZE];
2324   unsigned char *p;
2325   unsigned int total_reloc_size = 0;
2326   unsigned int subspace_reloc_size = 0;
2327   unsigned int num_spaces = obj_som_file_hdr (abfd)->space_total;
2328   asection *section = abfd->sections;
2329
2330   memset (tmp_space, 0, SOM_TMP_BUFSIZE);
2331   p = tmp_space;
2332
2333   /* All the fixups for a particular subspace are emitted in a single
2334      stream.  All the subspaces for a particular space are emitted
2335      as a single stream.
2336
2337      So, to get all the locations correct one must iterate through all the
2338      spaces, for each space iterate through its subspaces and output a
2339      fixups stream.  */
2340   for (i = 0; i < num_spaces; i++)
2341     {
2342       asection *subsection;
2343
2344       /* Find a space.  */
2345       while (!som_is_space (section))
2346         section = section->next;
2347
2348       /* Now iterate through each of its subspaces.  */
2349       for (subsection = abfd->sections;
2350            subsection != NULL;
2351            subsection = subsection->next)
2352         {
2353           int reloc_offset, current_rounding_mode;
2354
2355           /* Find a subspace of this space.  */
2356           if (!som_is_subspace (subsection)
2357               || !som_is_container (section, subsection))
2358             continue;
2359
2360           /* If this subspace does not have real data, then we are
2361              finised with it.  */
2362           if ((subsection->flags & (SEC_LOAD | SEC_DEBUGGING)) == 0)
2363             {
2364               som_section_data (subsection)->subspace_dict->fixup_request_index
2365                 = -1;
2366               continue;
2367             }
2368
2369           /* This subspace has some relocations.  Put the relocation stream
2370              index into the subspace record.  */
2371           som_section_data (subsection)->subspace_dict->fixup_request_index
2372             = total_reloc_size;
2373
2374           /* To make life easier start over with a clean slate for 
2375              each subspace.  Seek to the start of the relocation stream
2376              for this subspace in preparation for writing out its fixup
2377              stream.  */
2378           if (bfd_seek (abfd, current_offset + total_reloc_size, SEEK_SET) < 0)
2379             return false;
2380
2381           /* Buffer space has already been allocated.  Just perform some
2382              initialization here.  */
2383           p = tmp_space;
2384           subspace_reloc_size = 0;
2385           reloc_offset = 0;
2386           som_initialize_reloc_queue (reloc_queue);
2387           current_rounding_mode = R_N_MODE;
2388
2389           /* Translate each BFD relocation into one or more SOM 
2390              relocations.  */
2391           for (j = 0; j < subsection->reloc_count; j++)
2392             {
2393               arelent *bfd_reloc = subsection->orelocation[j];
2394               unsigned int skip;
2395               int sym_num;
2396
2397               /* Get the symbol number.  Remember it's stored in a 
2398                  special place for section symbols.  */
2399               if ((*bfd_reloc->sym_ptr_ptr)->flags & BSF_SECTION_SYM)
2400                 sym_num = (int) (*bfd_reloc->sym_ptr_ptr)->udata;
2401               else
2402                 sym_num = som_symbol_data (*bfd_reloc->sym_ptr_ptr)->index;
2403               
2404               /* If there is not enough room for the next couple relocations,
2405                  then dump the current buffer contents now.  Also reinitialize
2406                  the relocation queue. 
2407
2408                  No single BFD relocation could ever translate into more
2409                  than 100 bytes of SOM relocations (20bytes is probably the
2410                  upper limit, but leave lots of space for growth).  */
2411               if (p - tmp_space + 100 > SOM_TMP_BUFSIZE)
2412                 {
2413                   if (bfd_write ((PTR) tmp_space, p - tmp_space, 1, abfd)
2414                       != p - tmp_space)
2415                     return false;
2416
2417                   p = tmp_space;
2418                   som_initialize_reloc_queue (reloc_queue);
2419                 }
2420
2421               /* Emit R_NO_RELOCATION fixups to map any bytes which were
2422                  skipped.  */
2423               skip = bfd_reloc->address - reloc_offset;
2424               p = som_reloc_skip (abfd, skip, p,
2425                                   &subspace_reloc_size, reloc_queue);
2426
2427               /* Update reloc_offset for the next iteration.
2428
2429                  Many relocations do not consume input bytes.  They
2430                  are markers, or set state necessary to perform some
2431                  later relocation.  */
2432               switch (bfd_reloc->howto->type)
2433                 {
2434                 /* This only needs to handle relocations that may be
2435                    made by hppa_som_gen_reloc.  */
2436                 case R_ENTRY:
2437                 case R_EXIT:
2438                 case R_N_MODE:
2439                 case R_S_MODE:
2440                 case R_D_MODE:
2441                 case R_R_MODE:
2442                 case R_FSEL:
2443                 case R_LSEL:
2444                 case R_RSEL:
2445                   reloc_offset = bfd_reloc->address;
2446                   break;
2447
2448                 default:
2449                   reloc_offset = bfd_reloc->address + 4;
2450                   break;
2451                 }
2452
2453               /* Now the actual relocation we care about.  */
2454               switch (bfd_reloc->howto->type)
2455                 {
2456                 case R_PCREL_CALL:
2457                 case R_ABS_CALL:
2458                   p = som_reloc_call (abfd, p, &subspace_reloc_size,
2459                                       bfd_reloc, sym_num, reloc_queue);
2460                   break;
2461
2462                 case R_CODE_ONE_SYMBOL:
2463                 case R_DP_RELATIVE:
2464                   /* Account for any addend.  */
2465                   if (bfd_reloc->addend)
2466                     p = som_reloc_addend (abfd, bfd_reloc->addend, p, 
2467                                           &subspace_reloc_size, reloc_queue);
2468
2469                   if (sym_num < 0x20)
2470                     {
2471                       bfd_put_8 (abfd, bfd_reloc->howto->type + sym_num, p);
2472                       subspace_reloc_size += 1;
2473                       p += 1;
2474                     }
2475                   else if (sym_num < 0x100)
2476                     {
2477                       bfd_put_8 (abfd, bfd_reloc->howto->type + 32, p);
2478                       bfd_put_8 (abfd, sym_num, p + 1);
2479                       p = try_prev_fixup (abfd, &subspace_reloc_size, p,
2480                                           2, reloc_queue);
2481                     }
2482                   else if (sym_num < 0x10000000)
2483                     {
2484                       bfd_put_8 (abfd, bfd_reloc->howto->type + 33, p);
2485                       bfd_put_8 (abfd, sym_num >> 16, p + 1);
2486                       bfd_put_16 (abfd, sym_num, p + 2); 
2487                       p = try_prev_fixup (abfd, &subspace_reloc_size,
2488                                           p, 4, reloc_queue);
2489                     }
2490                   else
2491                     abort ();
2492                   break;
2493
2494                 case R_DATA_ONE_SYMBOL:
2495                 case R_DATA_PLABEL:
2496                 case R_CODE_PLABEL:
2497                 case R_DLT_REL:
2498                   /* Account for any addend.  */
2499                   if (bfd_reloc->addend)
2500                     p = som_reloc_addend (abfd, bfd_reloc->addend, p, 
2501                                           &subspace_reloc_size, reloc_queue);
2502
2503                   if (sym_num < 0x100)
2504                     {
2505                       bfd_put_8 (abfd, bfd_reloc->howto->type, p);
2506                       bfd_put_8 (abfd, sym_num, p + 1);
2507                       p = try_prev_fixup (abfd, &subspace_reloc_size, p,
2508                                           2, reloc_queue);
2509                     }
2510                   else if (sym_num < 0x10000000)
2511                     {
2512                       bfd_put_8 (abfd, bfd_reloc->howto->type + 1, p);
2513                       bfd_put_8 (abfd, sym_num >> 16, p + 1);
2514                       bfd_put_16 (abfd, sym_num, p + 2); 
2515                       p = try_prev_fixup (abfd, &subspace_reloc_size,
2516                                           p, 4, reloc_queue);
2517                     }
2518                   else
2519                     abort ();
2520                   break;
2521
2522                 case R_ENTRY:
2523                   {
2524                     int *descp = (int *)
2525                       som_symbol_data (*bfd_reloc->sym_ptr_ptr)->unwind;
2526                     bfd_put_8 (abfd, R_ENTRY, p);
2527
2528                     /* FIXME:  We should set the sym_ptr for the R_ENTRY
2529                        reloc to point to the appropriate function symbol,
2530                        and attach unwind bits to the function symbol as
2531                        we canonicalize the relocs.  Doing so would ensure
2532                        descp would always point to something useful.  */
2533                     if (descp)
2534                       {
2535                         bfd_put_32 (abfd, descp[0], p + 1);
2536                         bfd_put_32 (abfd, descp[1], p + 5);
2537                       }
2538                     else
2539                       {
2540                         bfd_put_32 (abfd, 0, p + 1);
2541                         bfd_put_32 (abfd, 0, p + 5);
2542                       }
2543                     p = try_prev_fixup (abfd, &subspace_reloc_size,
2544                                         p, 9, reloc_queue);
2545                     break;
2546                   }
2547                   
2548                 case R_EXIT:
2549                   bfd_put_8 (abfd, R_EXIT, p);
2550                   subspace_reloc_size += 1;
2551                   p += 1;
2552                   break;
2553
2554                 case R_N_MODE:
2555                 case R_S_MODE:
2556                 case R_D_MODE:
2557                 case R_R_MODE:
2558                   /* If this relocation requests the current rounding
2559                      mode, then it is redundant.  */
2560                   if (bfd_reloc->howto->type != current_rounding_mode)
2561                     {
2562                       bfd_put_8 (abfd, bfd_reloc->howto->type, p);
2563                       subspace_reloc_size += 1;
2564                       p += 1;
2565                       current_rounding_mode = bfd_reloc->howto->type;
2566                     }
2567                   break;
2568
2569                 case R_FSEL:
2570                 case R_LSEL:
2571                 case R_RSEL:
2572                   bfd_put_8 (abfd, bfd_reloc->howto->type, p);
2573                   subspace_reloc_size += 1;
2574                   p += 1;
2575                   break;
2576
2577                 /* Put a "R_RESERVED" relocation in the stream if
2578                    we hit something we do not understand.  The linker
2579                    will complain loudly if this ever happens.  */
2580                 default:
2581                   bfd_put_8 (abfd, 0xff, p);
2582                   subspace_reloc_size += 1;
2583                   p += 1;
2584                   break;
2585                 }
2586             }
2587
2588           /* Last BFD relocation for a subspace has been processed.
2589              Map the rest of the subspace with R_NO_RELOCATION fixups.  */
2590           p = som_reloc_skip (abfd, bfd_section_size (abfd, subsection) 
2591                                       - reloc_offset,
2592                               p, &subspace_reloc_size, reloc_queue);
2593
2594           /* Scribble out the relocations.  */
2595           if (bfd_write ((PTR) tmp_space, p - tmp_space, 1, abfd)
2596               != p - tmp_space)
2597             return false;
2598           p = tmp_space;
2599
2600           total_reloc_size += subspace_reloc_size;
2601           som_section_data (subsection)->subspace_dict->fixup_request_quantity
2602             = subspace_reloc_size;
2603         }
2604       section = section->next;
2605     }
2606   *total_reloc_sizep = total_reloc_size;
2607   return true;
2608 }
2609
2610 /* Write out the space/subspace string table.  */
2611
2612 static boolean
2613 som_write_space_strings (abfd, current_offset, string_sizep)
2614      bfd *abfd;
2615      unsigned long current_offset;
2616      unsigned int *string_sizep;
2617 {
2618   /* Chunk of memory that we can use as buffer space, then throw
2619      away.  */
2620   unsigned char tmp_space[SOM_TMP_BUFSIZE];
2621   unsigned char *p;
2622   unsigned int strings_size = 0;
2623   asection *section;
2624
2625   memset (tmp_space, 0, SOM_TMP_BUFSIZE);
2626   p = tmp_space;
2627
2628   /* Seek to the start of the space strings in preparation for writing
2629      them out.  */
2630   if (bfd_seek (abfd, current_offset, SEEK_SET) < 0)
2631     return false;
2632
2633   /* Walk through all the spaces and subspaces (order is not important)
2634      building up and writing string table entries for their names.  */
2635   for (section = abfd->sections; section != NULL; section = section->next)
2636     {
2637       int length;
2638
2639       /* Only work with space/subspaces; avoid any other sections
2640          which might have been made (.text for example).  */
2641       if (!som_is_space (section) && !som_is_subspace (section))
2642         continue;
2643
2644       /* Get the length of the space/subspace name.  */
2645       length = strlen (section->name);
2646
2647       /* If there is not enough room for the next entry, then dump the
2648          current buffer contents now.  Each entry will take 4 bytes to
2649          hold the string length + the string itself + null terminator.  */
2650       if (p - tmp_space + 5 + length > SOM_TMP_BUFSIZE)
2651         {
2652           if (bfd_write ((PTR) &tmp_space[0], p - tmp_space, 1, abfd)
2653               != p - tmp_space) 
2654             return false;
2655           /* Reset to beginning of the buffer space.  */
2656           p = tmp_space;
2657         }
2658
2659       /* First element in a string table entry is the length of the
2660          string.  Alignment issues are already handled.  */
2661       bfd_put_32 (abfd, length, p);
2662       p += 4;
2663       strings_size += 4;
2664
2665       /* Record the index in the space/subspace records.  */
2666       if (som_is_space (section))
2667         som_section_data (section)->space_dict->name.n_strx = strings_size;
2668       else
2669         som_section_data (section)->subspace_dict->name.n_strx = strings_size;
2670
2671       /* Next comes the string itself + a null terminator.  */
2672       strcpy (p, section->name);
2673       p += length + 1;
2674       strings_size += length + 1;
2675
2676       /* Always align up to the next word boundary.  */
2677       while (strings_size % 4)
2678         {
2679           bfd_put_8 (abfd, 0, p);
2680           p++;
2681           strings_size++;
2682         }
2683     }
2684
2685   /* Done with the space/subspace strings.  Write out any information
2686      contained in a partial block.  */
2687   if (bfd_write ((PTR) &tmp_space[0], p - tmp_space, 1, abfd) != p - tmp_space)
2688     return false;
2689   *string_sizep = strings_size;
2690   return true;
2691 }
2692
2693 /* Write out the symbol string table.  */
2694
2695 static boolean
2696 som_write_symbol_strings (abfd, current_offset, syms, num_syms, string_sizep)
2697      bfd *abfd;
2698      unsigned long current_offset;
2699      asymbol **syms;
2700      unsigned int num_syms;
2701      unsigned int *string_sizep;
2702 {
2703   unsigned int i;
2704   
2705   /* Chunk of memory that we can use as buffer space, then throw
2706      away.  */
2707   unsigned char tmp_space[SOM_TMP_BUFSIZE];
2708   unsigned char *p;
2709   unsigned int strings_size = 0;
2710
2711   memset (tmp_space, 0, SOM_TMP_BUFSIZE);
2712   p = tmp_space;
2713
2714   /* Seek to the start of the space strings in preparation for writing
2715      them out.  */
2716   if (bfd_seek (abfd, current_offset, SEEK_SET) < 0)
2717     return false;
2718
2719   for (i = 0; i < num_syms; i++)
2720     {
2721       int length = strlen (syms[i]->name);
2722
2723       /* If there is not enough room for the next entry, then dump the
2724          current buffer contents now.  */
2725      if (p - tmp_space + 5 + length > SOM_TMP_BUFSIZE)
2726         {
2727           if (bfd_write ((PTR) &tmp_space[0], p - tmp_space, 1, abfd)
2728               != p - tmp_space)
2729             return false;
2730           /* Reset to beginning of the buffer space.  */
2731           p = tmp_space;
2732         }
2733
2734       /* First element in a string table entry is the length of the
2735          string.  This must always be 4 byte aligned.  This is also
2736          an appropriate time to fill in the string index field in the
2737          symbol table entry.  */
2738       bfd_put_32 (abfd, length, p);
2739       strings_size += 4;
2740       p += 4;
2741
2742       /* Next comes the string itself + a null terminator.  */
2743       strcpy (p, syms[i]->name);
2744
2745       /* ACK.  FIXME.  */
2746       syms[i]->name = (char *)strings_size;
2747       p += length + 1;
2748       strings_size += length + 1;
2749
2750       /* Always align up to the next word boundary.  */
2751       while (strings_size % 4)
2752         {
2753           bfd_put_8 (abfd, 0, p);
2754           strings_size++;
2755           p++;
2756         }
2757     }
2758
2759   /* Scribble out any partial block.  */
2760   if (bfd_write ((PTR) &tmp_space[0], p - tmp_space, 1, abfd) != p - tmp_space)
2761     return false;
2762
2763   *string_sizep = strings_size;
2764   return true;
2765 }
2766
2767 /* Compute variable information to be placed in the SOM headers, 
2768    space/subspace dictionaries, relocation streams, etc.  Begin
2769    writing parts of the object file.  */
2770
2771 static boolean 
2772 som_begin_writing (abfd)
2773      bfd *abfd;
2774 {
2775   unsigned long current_offset = 0;
2776   int strings_size = 0;
2777   unsigned int total_reloc_size = 0;
2778   unsigned long num_spaces, num_subspaces, num_syms, i;
2779   asection *section;
2780   asymbol **syms = bfd_get_outsymbols (abfd);
2781   unsigned int total_subspaces = 0;
2782   struct som_exec_auxhdr *exec_header;
2783
2784   /* The file header will always be first in an object file, 
2785      everything else can be in random locations.  To keep things
2786      "simple" BFD will lay out the object file in the manner suggested
2787      by the PRO ABI for PA-RISC Systems.  */
2788
2789   /* Before any output can really begin offsets for all the major
2790      portions of the object file must be computed.  So, starting
2791      with the initial file header compute (and sometimes write)
2792      each portion of the object file.  */
2793
2794   /* Make room for the file header, it's contents are not complete
2795      yet, so it can not be written at this time.  */
2796   current_offset += sizeof (struct header);  
2797
2798   /* Any auxiliary headers will follow the file header.  Right now
2799      we support only the copyright and version headers.  */
2800   obj_som_file_hdr (abfd)->aux_header_location = current_offset;
2801   obj_som_file_hdr (abfd)->aux_header_size = 0;
2802   if (abfd->flags & (EXEC_P | DYNAMIC))
2803     {
2804       /* Parts of the exec header will be filled in later, so
2805          delay writing the header itself.  Fill in the defaults,
2806          and write it later.  */
2807       current_offset += sizeof (struct som_exec_auxhdr);
2808       obj_som_file_hdr (abfd)->aux_header_size
2809         += sizeof (struct som_exec_auxhdr);
2810       exec_header = obj_som_exec_hdr (abfd);
2811       exec_header->som_auxhdr.type = EXEC_AUX_ID;
2812       exec_header->som_auxhdr.length = 40;
2813     }
2814   if (obj_som_version_hdr (abfd) != NULL)
2815     {
2816       unsigned int len;
2817
2818       if (bfd_seek (abfd, current_offset, SEEK_SET) < 0)
2819         return false;
2820
2821       /* Write the aux_id structure and the string length.  */
2822       len = sizeof (struct aux_id) + sizeof (unsigned int);
2823       obj_som_file_hdr (abfd)->aux_header_size += len;
2824       current_offset += len;
2825       if (bfd_write ((PTR) obj_som_version_hdr (abfd), len, 1, abfd) != len)
2826         return false;
2827
2828       /* Write the version string.  */
2829       len = obj_som_version_hdr (abfd)->header_id.length - sizeof (int);
2830       obj_som_file_hdr (abfd)->aux_header_size += len;
2831       current_offset += len;
2832       if (bfd_write ((PTR) obj_som_version_hdr (abfd)->user_string,
2833                      len, 1, abfd) != len)
2834         return false;
2835     }
2836
2837   if (obj_som_copyright_hdr (abfd) != NULL)
2838     {
2839       unsigned int len;
2840
2841       if (bfd_seek (abfd, current_offset, SEEK_SET) < 0)
2842         return false;
2843
2844       /* Write the aux_id structure and the string length.  */
2845       len = sizeof (struct aux_id) + sizeof (unsigned int);
2846       obj_som_file_hdr (abfd)->aux_header_size += len;
2847       current_offset += len;
2848       if (bfd_write ((PTR) obj_som_copyright_hdr (abfd), len, 1, abfd) != len)
2849         return false;
2850
2851       /* Write the copyright string.  */
2852       len = obj_som_copyright_hdr (abfd)->header_id.length - sizeof (int);
2853       obj_som_file_hdr (abfd)->aux_header_size += len;
2854       current_offset += len;
2855       if (bfd_write ((PTR) obj_som_copyright_hdr (abfd)->copyright,
2856                      len, 1, abfd) != len)
2857         return false;
2858     }
2859
2860   /* Next comes the initialization pointers; we have no initialization
2861      pointers, so current offset does not change.  */
2862   obj_som_file_hdr (abfd)->init_array_location = current_offset;
2863   obj_som_file_hdr (abfd)->init_array_total = 0;
2864
2865   /* Next are the space records.  These are fixed length records.
2866
2867      Count the number of spaces to determine how much room is needed
2868      in the object file for the space records.
2869
2870      The names of the spaces are stored in a separate string table,
2871      and the index for each space into the string table is computed
2872      below.  Therefore, it is not possible to write the space headers
2873      at this time.  */
2874   num_spaces = som_count_spaces (abfd);
2875   obj_som_file_hdr (abfd)->space_location = current_offset;
2876   obj_som_file_hdr (abfd)->space_total = num_spaces;
2877   current_offset += num_spaces * sizeof (struct space_dictionary_record);
2878
2879   /* Next are the subspace records.  These are fixed length records.
2880
2881      Count the number of subspaes to determine how much room is needed
2882      in the object file for the subspace records.
2883
2884      A variety if fields in the subspace record are still unknown at
2885      this time (index into string table, fixup stream location/size, etc).  */
2886   num_subspaces = som_count_subspaces (abfd);
2887   obj_som_file_hdr (abfd)->subspace_location = current_offset;
2888   obj_som_file_hdr (abfd)->subspace_total = num_subspaces;
2889   current_offset += num_subspaces * sizeof (struct subspace_dictionary_record);
2890
2891   /* Next is the string table for the space/subspace names.  We will
2892      build and write the string table on the fly.  At the same time
2893      we will fill in the space/subspace name index fields.  */
2894
2895   /* The string table needs to be aligned on a word boundary.  */
2896   if (current_offset % 4)
2897     current_offset += (4 - (current_offset % 4));
2898
2899   /* Mark the offset of the space/subspace string table in the 
2900      file header.  */
2901   obj_som_file_hdr (abfd)->space_strings_location = current_offset;
2902
2903   /* Scribble out the space strings.  */
2904   if (som_write_space_strings (abfd, current_offset, &strings_size) == false)
2905     return false;
2906
2907   /* Record total string table size in the header and update the
2908      current offset.  */
2909   obj_som_file_hdr (abfd)->space_strings_size = strings_size;
2910   current_offset += strings_size;
2911
2912   /* Next is the symbol table.  These are fixed length records.
2913
2914      Count the number of symbols to determine how much room is needed
2915      in the object file for the symbol table.
2916
2917      The names of the symbols are stored in a separate string table,
2918      and the index for each symbol name into the string table is computed
2919      below.  Therefore, it is not possible to write the symobl table
2920      at this time.  */
2921   num_syms = bfd_get_symcount (abfd);
2922   obj_som_file_hdr (abfd)->symbol_location = current_offset;
2923   obj_som_file_hdr (abfd)->symbol_total = num_syms;
2924   current_offset += num_syms * sizeof (struct symbol_dictionary_record);
2925
2926   /* Do prep work before handling fixups.  */
2927   som_prep_for_fixups (abfd, syms, num_syms);
2928
2929   /* Next comes the fixup stream which starts on a word boundary.  */
2930   if (current_offset % 4)
2931     current_offset += (4 - (current_offset % 4)); 
2932   obj_som_file_hdr (abfd)->fixup_request_location = current_offset;
2933
2934   /* Write the fixups and update fields in subspace headers which
2935      relate to the fixup stream.  */
2936   if (som_write_fixups (abfd, current_offset, &total_reloc_size) == false)
2937     return false;
2938
2939   /* Record the total size of the fixup stream in the file header.  */
2940   obj_som_file_hdr (abfd)->fixup_request_total = total_reloc_size;
2941   current_offset += total_reloc_size;
2942
2943   /* Next are the symbol strings.
2944      Align them to a word boundary.  */
2945   if (current_offset % 4)
2946     current_offset += (4 - (current_offset % 4));
2947   obj_som_file_hdr (abfd)->symbol_strings_location = current_offset;
2948
2949   /* Scribble out the symbol strings.  */
2950   if (som_write_symbol_strings (abfd, current_offset, syms, 
2951                                 num_syms, &strings_size)
2952       == false)
2953     return false;
2954
2955   /* Record total string table size in header and update the
2956      current offset.  */
2957   obj_som_file_hdr (abfd)->symbol_strings_size = strings_size;
2958   current_offset += strings_size;
2959
2960   /* Next is the compiler records.  We do not use these.  */
2961   obj_som_file_hdr (abfd)->compiler_location = current_offset;
2962   obj_som_file_hdr (abfd)->compiler_total = 0;
2963
2964   /* Now compute the file positions for the loadable subspaces, taking
2965      care to make sure everything stays properly aligned.  */
2966
2967   section = abfd->sections;
2968   for (i = 0; i < num_spaces; i++)
2969     {
2970       asection *subsection;
2971       int first_subspace;
2972       unsigned int subspace_offset = 0;
2973
2974       /* Find a space.  */
2975       while (!som_is_space (section))
2976         section = section->next;
2977
2978       first_subspace = 1;
2979       /* Now look for all its subspaces.  */
2980       for (subsection = abfd->sections;
2981            subsection != NULL;
2982            subsection = subsection->next)
2983         {
2984
2985           if (!som_is_subspace (subsection)
2986               || !som_is_container (section, subsection)
2987               || (subsection->flags & SEC_ALLOC) == 0)
2988             continue;
2989
2990           /* If this is the first subspace in the space, and we are
2991              building an executable, then take care to make sure all
2992              the alignments are correct and update the exec header.  */
2993           if (first_subspace
2994               && (abfd->flags & (EXEC_P | DYNAMIC)))
2995             {
2996               /* Demand paged executables have each space aligned to a
2997                  page boundary.  Sharable executables (write-protected
2998                  text) have just the private (aka data & bss) space aligned
2999                  to a page boundary.  Ugh.  Not true for HPUX.
3000
3001                  The HPUX kernel requires the text to always be page aligned
3002                  within the file regardless of the executable's type.  */
3003               if (abfd->flags & (D_PAGED | DYNAMIC)
3004                   || (subsection->flags & SEC_CODE)
3005                   || ((abfd->flags & WP_TEXT)
3006                       && (subsection->flags & SEC_DATA)))
3007                 current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
3008
3009               /* Update the exec header.  */
3010               if (subsection->flags & SEC_CODE && exec_header->exec_tfile == 0)
3011                 {
3012                   exec_header->exec_tmem = section->vma;
3013                   exec_header->exec_tfile = current_offset;
3014                 }
3015               if (subsection->flags & SEC_DATA && exec_header->exec_dfile == 0)
3016                 {
3017                   exec_header->exec_dmem = section->vma;
3018                   exec_header->exec_dfile = current_offset;
3019                 }
3020
3021               /* Keep track of exactly where we are within a particular
3022                  space.  This is necessary as the braindamaged HPUX
3023                  loader will create holes between subspaces *and* 
3024                  subspace alignments are *NOT* preserved.  What a crock.  */
3025               subspace_offset = subsection->vma;
3026
3027               /* Only do this for the first subspace within each space.  */
3028               first_subspace = 0;
3029             }
3030           else if (abfd->flags & (EXEC_P | DYNAMIC))
3031             {
3032               /* The braindamaged HPUX loader may have created a hole
3033                  between two subspaces.  It is *not* sufficient to use
3034                  the alignment specifications within the subspaces to
3035                  account for these holes -- I've run into at least one
3036                  case where the loader left one code subspace unaligned
3037                  in a final executable.
3038
3039                  To combat this we keep a current offset within each space,
3040                  and use the subspace vma fields to detect and preserve
3041                  holes.  What a crock!
3042
3043                  ps.  This is not necessary for unloadable space/subspaces.  */
3044               current_offset += subsection->vma - subspace_offset;
3045               if (subsection->flags & SEC_CODE)
3046                 exec_header->exec_tsize += subsection->vma - subspace_offset;
3047               else
3048                 exec_header->exec_dsize += subsection->vma - subspace_offset;
3049               subspace_offset += subsection->vma - subspace_offset;
3050             }
3051
3052
3053           subsection->target_index = total_subspaces++;
3054           /* This is real data to be loaded from the file.  */
3055           if (subsection->flags & SEC_LOAD)
3056             {
3057               /* Update the size of the code & data.  */
3058               if (abfd->flags & (EXEC_P | DYNAMIC)
3059                   && subsection->flags & SEC_CODE)
3060                 exec_header->exec_tsize += subsection->_cooked_size;
3061               else if (abfd->flags & (EXEC_P | DYNAMIC)
3062                        && subsection->flags & SEC_DATA)
3063                 exec_header->exec_dsize += subsection->_cooked_size;
3064               som_section_data (subsection)->subspace_dict->file_loc_init_value
3065                 = current_offset;
3066               subsection->filepos = current_offset;
3067               current_offset += bfd_section_size (abfd, subsection); 
3068               subspace_offset += bfd_section_size (abfd, subsection);
3069             }
3070           /* Looks like uninitialized data.  */
3071           else
3072             {
3073               /* Update the size of the bss section.  */
3074               if (abfd->flags & (EXEC_P | DYNAMIC))
3075                 exec_header->exec_bsize += subsection->_cooked_size;
3076
3077               som_section_data (subsection)->subspace_dict->file_loc_init_value
3078                 = 0;
3079               som_section_data (subsection)->subspace_dict->
3080                 initialization_length = 0;
3081             }
3082         }
3083       /* Goto the next section.  */
3084       section = section->next; 
3085     }
3086
3087   /* Finally compute the file positions for unloadable subspaces.
3088      If building an executable, start the unloadable stuff on its
3089      own page.  */
3090
3091   if (abfd->flags & (EXEC_P | DYNAMIC))
3092     current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
3093
3094   obj_som_file_hdr (abfd)->unloadable_sp_location = current_offset;
3095   section = abfd->sections;
3096   for (i = 0; i < num_spaces; i++)
3097     {
3098       asection *subsection;
3099
3100       /* Find a space.  */
3101       while (!som_is_space (section))
3102         section = section->next;
3103
3104       if (abfd->flags & (EXEC_P | DYNAMIC))
3105         current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
3106
3107       /* Now look for all its subspaces.  */
3108       for (subsection = abfd->sections;
3109            subsection != NULL;
3110            subsection = subsection->next)
3111         {
3112           
3113           if (!som_is_subspace (subsection)
3114               || !som_is_container (section, subsection)
3115               || (subsection->flags & SEC_ALLOC) != 0)
3116             continue;
3117
3118           subsection->target_index = total_subspaces;
3119           /* This is real data to be loaded from the file.  */
3120           if ((subsection->flags & SEC_LOAD) == 0)
3121             {
3122               som_section_data (subsection)->subspace_dict->file_loc_init_value
3123                 = current_offset;
3124               subsection->filepos = current_offset;
3125               current_offset += bfd_section_size (abfd, subsection); 
3126             }
3127           /* Looks like uninitialized data.  */
3128           else
3129             {
3130               som_section_data (subsection)->subspace_dict->file_loc_init_value
3131                 = 0;
3132               som_section_data (subsection)->subspace_dict->
3133                 initialization_length = bfd_section_size (abfd, subsection);
3134             }
3135         }
3136       /* Goto the next section.  */
3137       section = section->next; 
3138     }
3139
3140   /* If building an executable, then make sure to seek to and write
3141      one byte at the end of the file to make sure any necessary
3142      zeros are filled in.  Ugh.  */
3143   if (abfd->flags & (EXEC_P | DYNAMIC))
3144     current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
3145   if (bfd_seek (abfd, current_offset - 1, SEEK_SET) < 0)
3146     return false;
3147   if (bfd_write ((PTR) "", 1, 1, abfd) != 1)
3148     return false;
3149
3150   obj_som_file_hdr (abfd)->unloadable_sp_size
3151     = current_offset - obj_som_file_hdr (abfd)->unloadable_sp_location;
3152
3153   /* Loader fixups are not supported in any way shape or form.  */
3154   obj_som_file_hdr (abfd)->loader_fixup_location = 0;
3155   obj_som_file_hdr (abfd)->loader_fixup_total = 0;
3156
3157   /* Done.  Store the total size of the SOM.  */
3158   obj_som_file_hdr (abfd)->som_length = current_offset;
3159
3160   return true;
3161 }
3162
3163 /* Finally, scribble out the various headers to the disk.  */
3164
3165 static boolean
3166 som_write_headers (abfd)
3167      bfd *abfd;
3168 {
3169   int num_spaces = som_count_spaces (abfd);
3170   int i;
3171   int subspace_index = 0;
3172   file_ptr location;
3173   asection *section;
3174
3175   /* Subspaces are written first so that we can set up information
3176      about them in their containing spaces as the subspace is written.  */
3177
3178   /* Seek to the start of the subspace dictionary records.  */
3179   location = obj_som_file_hdr (abfd)->subspace_location;
3180   if (bfd_seek (abfd, location, SEEK_SET) < 0)
3181     return false;
3182
3183   section = abfd->sections;
3184   /* Now for each loadable space write out records for its subspaces.  */
3185   for (i = 0; i < num_spaces; i++)
3186     {
3187       asection *subsection;
3188
3189       /* Find a space.  */
3190       while (!som_is_space (section))
3191         section = section->next;
3192
3193       /* Now look for all its subspaces.  */
3194       for (subsection = abfd->sections;
3195            subsection != NULL;
3196            subsection = subsection->next)
3197         {
3198           
3199           /* Skip any section which does not correspond to a space
3200              or subspace.  Or does not have SEC_ALLOC set (and therefore
3201              has no real bits on the disk).  */
3202           if (!som_is_subspace (subsection)
3203               || !som_is_container (section, subsection)
3204               || (subsection->flags & SEC_ALLOC) == 0)
3205             continue;
3206
3207           /* If this is the first subspace for this space, then save
3208              the index of the subspace in its containing space.  Also
3209              set "is_loadable" in the containing space.  */
3210
3211           if (som_section_data (section)->space_dict->subspace_quantity == 0)
3212             {
3213               som_section_data (section)->space_dict->is_loadable = 1;
3214               som_section_data (section)->space_dict->subspace_index
3215                 = subspace_index;
3216             }
3217
3218           /* Increment the number of subspaces seen and the number of
3219              subspaces contained within the current space.  */
3220           subspace_index++;
3221           som_section_data (section)->space_dict->subspace_quantity++;
3222
3223           /* Mark the index of the current space within the subspace's
3224              dictionary record.  */
3225           som_section_data (subsection)->subspace_dict->space_index = i;
3226           
3227           /* Dump the current subspace header.  */
3228           if (bfd_write ((PTR) som_section_data (subsection)->subspace_dict,
3229                          sizeof (struct subspace_dictionary_record), 1, abfd)
3230               != sizeof (struct subspace_dictionary_record))
3231             return false;
3232         }
3233       /* Goto the next section.  */
3234       section = section->next; 
3235     }
3236
3237   /* Now repeat the process for unloadable subspaces.  */
3238   section = abfd->sections;
3239   /* Now for each space write out records for its subspaces.  */
3240   for (i = 0; i < num_spaces; i++)
3241     {
3242       asection *subsection;
3243
3244       /* Find a space.  */
3245       while (!som_is_space (section))
3246         section = section->next;
3247
3248       /* Now look for all its subspaces.  */
3249       for (subsection = abfd->sections;
3250            subsection != NULL;
3251            subsection = subsection->next)
3252         {
3253           
3254           /* Skip any section which does not correspond to a space or
3255              subspace, or which SEC_ALLOC set (and therefore handled
3256              in the loadable spaces/subspaces code above).  */
3257
3258           if (!som_is_subspace (subsection)
3259               || !som_is_container (section, subsection)
3260               || (subsection->flags & SEC_ALLOC) != 0)
3261             continue;
3262
3263           /* If this is the first subspace for this space, then save
3264              the index of the subspace in its containing space.  Clear
3265              "is_loadable".  */
3266
3267           if (som_section_data (section)->space_dict->subspace_quantity == 0)
3268             {
3269               som_section_data (section)->space_dict->is_loadable = 0;
3270               som_section_data (section)->space_dict->subspace_index
3271                 = subspace_index;
3272             }
3273
3274           /* Increment the number of subspaces seen and the number of
3275              subspaces contained within the current space.  */
3276           som_section_data (section)->space_dict->subspace_quantity++;
3277           subspace_index++; 
3278
3279           /* Mark the index of the current space within the subspace's
3280              dictionary record.  */
3281           som_section_data (subsection)->subspace_dict->space_index = i;
3282           
3283           /* Dump this subspace header.  */
3284           if (bfd_write ((PTR) som_section_data (subsection)->subspace_dict,
3285                          sizeof (struct subspace_dictionary_record), 1, abfd)
3286               != sizeof (struct subspace_dictionary_record))
3287             return false;
3288         }
3289       /* Goto the next section.  */
3290       section = section->next; 
3291     }
3292
3293   /* All the subspace dictiondary records are written, and all the
3294      fields are set up in the space dictionary records.
3295
3296      Seek to the right location and start writing the space
3297      dictionary records.  */
3298   location = obj_som_file_hdr (abfd)->space_location;
3299   if (bfd_seek (abfd, location, SEEK_SET) < 0)
3300     return false;
3301
3302   section = abfd->sections;
3303   for (i = 0; i < num_spaces; i++)
3304     {
3305
3306       /* Find a space.  */
3307       while (!som_is_space (section))
3308         section = section->next;
3309
3310       /* Dump its header  */
3311       if (bfd_write ((PTR) som_section_data (section)->space_dict,
3312                      sizeof (struct space_dictionary_record), 1, abfd)
3313           != sizeof (struct space_dictionary_record))
3314         return false;
3315
3316       /* Goto the next section.  */
3317       section = section->next;
3318     }
3319
3320   /* FIXME.  This should really be conditional based on whether or not
3321      PA1.1 instructions/registers have been used. 
3322
3323      Setting of the system_id has to happen very late now that copying of
3324      BFD private data happens *after* section contents are set.  */
3325   if (abfd->flags & (EXEC_P | DYNAMIC))
3326     obj_som_file_hdr(abfd)->system_id = obj_som_exec_data (abfd)->system_id;
3327   else
3328     obj_som_file_hdr(abfd)->system_id = CPU_PA_RISC1_0;
3329
3330   /* Compute the checksum for the file header just before writing
3331      the header to disk.  */
3332   obj_som_file_hdr (abfd)->checksum = som_compute_checksum (abfd);
3333
3334   /* Only thing left to do is write out the file header.  It is always
3335      at location zero.  Seek there and write it.  */
3336   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) < 0)
3337     return false;
3338   if (bfd_write ((PTR) obj_som_file_hdr (abfd),
3339                  sizeof (struct header), 1, abfd)
3340       != sizeof (struct header))
3341     return false;
3342
3343   /* Now write the exec header.  */
3344   if (abfd->flags & (EXEC_P | DYNAMIC))
3345     {
3346       long tmp;
3347       struct som_exec_auxhdr *exec_header;
3348
3349       exec_header = obj_som_exec_hdr (abfd);
3350       exec_header->exec_entry = bfd_get_start_address (abfd);
3351       exec_header->exec_flags = obj_som_exec_data (abfd)->exec_flags;
3352
3353       /* Oh joys.  Ram some of the BSS data into the DATA section
3354          to be compatable with how the hp linker makes objects
3355          (saves memory space).  */
3356       tmp = exec_header->exec_dsize;
3357       tmp = SOM_ALIGN (tmp, PA_PAGESIZE);
3358       exec_header->exec_bsize -= (tmp - exec_header->exec_dsize);
3359       if (exec_header->exec_bsize < 0)
3360         exec_header->exec_bsize = 0;
3361       exec_header->exec_dsize = tmp;
3362
3363       if (bfd_seek (abfd, obj_som_file_hdr (abfd)->aux_header_location,
3364                     SEEK_SET) < 0)
3365         return false;
3366
3367       if (bfd_write ((PTR) exec_header, AUX_HDR_SIZE, 1, abfd)
3368           != AUX_HDR_SIZE)
3369         return false;
3370     }
3371   return true;
3372 }
3373
3374 /* Compute and return the checksum for a SOM file header.  */
3375
3376 static unsigned long
3377 som_compute_checksum (abfd)
3378      bfd *abfd;
3379 {
3380   unsigned long checksum, count, i;
3381   unsigned long *buffer = (unsigned long *) obj_som_file_hdr (abfd);
3382
3383   checksum = 0;
3384   count = sizeof (struct header) / sizeof (unsigned long);
3385   for (i = 0; i < count; i++)
3386     checksum ^= *(buffer + i);
3387
3388   return checksum;
3389 }
3390
3391 static void
3392 som_bfd_derive_misc_symbol_info (abfd, sym, info)
3393      bfd *abfd;
3394      asymbol *sym;
3395      struct som_misc_symbol_info *info;
3396 {
3397   /* Initialize.  */
3398   memset (info, 0, sizeof (struct som_misc_symbol_info));
3399
3400   /* The HP SOM linker requires detailed type information about
3401      all symbols (including undefined symbols!).  Unfortunately,
3402      the type specified in an import/export statement does not
3403      always match what the linker wants.  Severe braindamage.  */
3404          
3405   /* Section symbols will not have a SOM symbol type assigned to
3406      them yet.  Assign all section symbols type ST_DATA.  */
3407   if (sym->flags & BSF_SECTION_SYM)
3408     info->symbol_type = ST_DATA;
3409   else
3410     {
3411       /* Common symbols must have scope SS_UNSAT and type
3412          ST_STORAGE or the linker will choke.  */
3413       if (bfd_is_com_section (sym->section))
3414         {
3415           info->symbol_scope = SS_UNSAT;
3416           info->symbol_type = ST_STORAGE;
3417         }
3418
3419       /* It is possible to have a symbol without an associated
3420          type.  This happens if the user imported the symbol
3421          without a type and the symbol was never defined
3422          locally.  If BSF_FUNCTION is set for this symbol, then
3423          assign it type ST_CODE (the HP linker requires undefined
3424          external functions to have type ST_CODE rather than ST_ENTRY).  */
3425       else if ((som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN
3426                 || som_symbol_data (sym)->som_type == SYMBOL_TYPE_CODE)
3427                && bfd_is_und_section (sym->section)
3428                && sym->flags & BSF_FUNCTION)
3429         info->symbol_type = ST_CODE;
3430
3431       /* Handle function symbols which were defined in this file.
3432          They should have type ST_ENTRY.  Also retrieve the argument
3433          relocation bits from the SOM backend information.  */
3434       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_ENTRY
3435                || (som_symbol_data (sym)->som_type == SYMBOL_TYPE_CODE
3436                    && (sym->flags & BSF_FUNCTION))
3437                || (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN
3438                    && (sym->flags & BSF_FUNCTION)))
3439         {
3440           info->symbol_type = ST_ENTRY;
3441           info->arg_reloc = som_symbol_data (sym)->tc_data.hppa_arg_reloc;
3442         }
3443
3444       /* If the type is unknown at this point, it should be ST_DATA or
3445          ST_CODE (function/ST_ENTRY symbols were handled  as special
3446          cases above). */
3447       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN)
3448         {
3449           if (sym->section->flags & SEC_CODE)
3450             info->symbol_type = ST_CODE;
3451           else
3452             info->symbol_type = ST_DATA;
3453         }
3454
3455       /* From now on it's a very simple mapping.  */
3456       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_ABSOLUTE)
3457         info->symbol_type = ST_ABSOLUTE;
3458       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_CODE)
3459         info->symbol_type = ST_CODE;
3460       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_DATA)
3461         info->symbol_type = ST_DATA;
3462       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_MILLICODE)
3463         info->symbol_type = ST_MILLICODE;
3464       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_PLABEL)
3465         info->symbol_type = ST_PLABEL;
3466       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_PRI_PROG)
3467         info->symbol_type = ST_PRI_PROG;
3468       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_SEC_PROG)
3469         info->symbol_type = ST_SEC_PROG;
3470     }
3471         
3472   /* Now handle the symbol's scope.  Exported data which is not
3473      in the common section has scope SS_UNIVERSAL.  Note scope
3474      of common symbols was handled earlier!  */
3475   if (sym->flags & BSF_EXPORT && ! bfd_is_com_section (sym->section))
3476     info->symbol_scope = SS_UNIVERSAL;
3477   /* Any undefined symbol at this point has a scope SS_UNSAT.  */
3478   else if (bfd_is_und_section (sym->section))
3479     info->symbol_scope = SS_UNSAT;
3480   /* Anything else which is not in the common section has scope
3481      SS_LOCAL.  */
3482   else if (! bfd_is_com_section (sym->section))
3483     info->symbol_scope = SS_LOCAL;
3484
3485   /* Now set the symbol_info field.  It has no real meaning
3486      for undefined or common symbols, but the HP linker will
3487      choke if it's not set to some "reasonable" value.  We
3488      use zero as a reasonable value.  */
3489   if (bfd_is_com_section (sym->section)
3490       || bfd_is_und_section (sym->section)
3491       || bfd_is_abs_section (sym->section))
3492     info->symbol_info = 0;
3493   /* For all other symbols, the symbol_info field contains the 
3494      subspace index of the space this symbol is contained in.  */
3495   else
3496     info->symbol_info = sym->section->target_index;
3497
3498   /* Set the symbol's value.  */
3499   info->symbol_value = sym->value + sym->section->vma;
3500 }
3501
3502 /* Build and write, in one big chunk, the entire symbol table for
3503    this BFD.  */
3504
3505 static boolean
3506 som_build_and_write_symbol_table (abfd)
3507      bfd *abfd;
3508 {
3509   unsigned int num_syms = bfd_get_symcount (abfd);
3510   file_ptr symtab_location = obj_som_file_hdr (abfd)->symbol_location;
3511   asymbol **bfd_syms = bfd_get_outsymbols (abfd);
3512   struct symbol_dictionary_record *som_symtab = NULL;
3513   int i, symtab_size;
3514
3515   /* Compute total symbol table size and allocate a chunk of memory
3516      to hold the symbol table as we build it.  */
3517   symtab_size = num_syms * sizeof (struct symbol_dictionary_record);
3518   som_symtab = (struct symbol_dictionary_record *) malloc (symtab_size);
3519   if (som_symtab == NULL && symtab_size != 0)
3520     {
3521       bfd_set_error (bfd_error_no_memory);
3522       goto error_return;
3523     }
3524   memset (som_symtab, 0, symtab_size);
3525
3526   /* Walk over each symbol.  */
3527   for (i = 0; i < num_syms; i++)
3528     {
3529       struct som_misc_symbol_info info;
3530
3531       /* This is really an index into the symbol strings table.  
3532          By the time we get here, the index has already been 
3533          computed and stored into the name field in the BFD symbol.  */
3534       som_symtab[i].name.n_strx = (int) bfd_syms[i]->name;
3535
3536       /* Derive SOM information from the BFD symbol.  */
3537       som_bfd_derive_misc_symbol_info (abfd, bfd_syms[i], &info);
3538
3539       /* Now use it.  */
3540       som_symtab[i].symbol_type = info.symbol_type;
3541       som_symtab[i].symbol_scope = info.symbol_scope;
3542       som_symtab[i].arg_reloc = info.arg_reloc;
3543       som_symtab[i].symbol_info = info.symbol_info;
3544       som_symtab[i].symbol_value = info.symbol_value;
3545     }
3546
3547   /* Everything is ready, seek to the right location and
3548      scribble out the symbol table.  */
3549   if (bfd_seek (abfd, symtab_location, SEEK_SET) != 0)
3550     return false;
3551
3552   if (bfd_write ((PTR) som_symtab, symtab_size, 1, abfd) != symtab_size)
3553     goto error_return;
3554
3555   if (som_symtab != NULL)
3556     free (som_symtab);
3557   return true;
3558  error_return:
3559   if (som_symtab != NULL)
3560     free (som_symtab);
3561   return false;
3562 }
3563
3564 /* Write an object in SOM format.  */  
3565
3566 static boolean
3567 som_write_object_contents (abfd)
3568      bfd *abfd;
3569 {
3570   if (abfd->output_has_begun == false)
3571     {
3572       /* Set up fixed parts of the file, space, and subspace headers.
3573          Notify the world that output has begun.  */
3574       som_prep_headers (abfd);
3575       abfd->output_has_begun = true;
3576       /* Start writing the object file.  This include all the string
3577          tables, fixup streams, and other portions of the object file.  */
3578       som_begin_writing (abfd);
3579     }
3580
3581   /* Now that the symbol table information is complete, build and
3582      write the symbol table.  */
3583   if (som_build_and_write_symbol_table (abfd) == false)
3584     return false;
3585
3586   return (som_write_headers (abfd));
3587 }
3588
3589 \f
3590 /* Read and save the string table associated with the given BFD.  */
3591
3592 static boolean
3593 som_slurp_string_table (abfd)
3594      bfd *abfd;
3595 {
3596   char *stringtab;
3597
3598   /* Use the saved version if its available.  */
3599   if (obj_som_stringtab (abfd) != NULL)
3600     return true;
3601
3602   /* I don't think this can currently happen, and I'm not sure it should
3603      really be an error, but it's better than getting unpredictable results
3604      from the host's malloc when passed a size of zero.  */
3605   if (obj_som_stringtab_size (abfd) == 0)
3606     {
3607       bfd_set_error (bfd_error_no_symbols);
3608       return false;
3609     }
3610
3611   /* Allocate and read in the string table.  */
3612   stringtab = malloc (obj_som_stringtab_size (abfd));
3613   if (stringtab == NULL)
3614     {
3615       bfd_set_error (bfd_error_no_memory);
3616       return false;
3617     }
3618
3619   if (bfd_seek (abfd, obj_som_str_filepos (abfd), SEEK_SET) < 0)
3620     return false;
3621   
3622   if (bfd_read (stringtab, obj_som_stringtab_size (abfd), 1, abfd)
3623       != obj_som_stringtab_size (abfd))
3624     return false;
3625
3626   /* Save our results and return success. */
3627   obj_som_stringtab (abfd) = stringtab;
3628   return true;
3629 }
3630
3631 /* Return the amount of data (in bytes) required to hold the symbol
3632    table for this object.  */
3633
3634 static long
3635 som_get_symtab_upper_bound (abfd)
3636      bfd *abfd;
3637 {
3638   if (!som_slurp_symbol_table (abfd))
3639     return -1;
3640
3641   return (bfd_get_symcount (abfd) + 1) * (sizeof (asymbol *));
3642 }
3643
3644 /* Convert from a SOM subspace index to a BFD section.  */
3645
3646 static asection *
3647 bfd_section_from_som_symbol (abfd, symbol)
3648      bfd *abfd;
3649      struct symbol_dictionary_record *symbol;
3650 {
3651   asection *section;
3652
3653   /* The meaning of the symbol_info field changes for functions
3654      within executables.  So only use the quick symbol_info mapping for
3655      incomplete objects and non-function symbols in executables.  */
3656   if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0
3657       || (symbol->symbol_type != ST_ENTRY
3658           && symbol->symbol_type != ST_PRI_PROG
3659           && symbol->symbol_type != ST_SEC_PROG
3660           && symbol->symbol_type != ST_MILLICODE))
3661     {
3662       unsigned int index = symbol->symbol_info;
3663       for (section = abfd->sections; section != NULL; section = section->next)
3664         if (section->target_index == index)
3665           return section;
3666
3667       /* Should never happen.  */
3668       abort();
3669     }
3670   else
3671     {
3672       unsigned int value = symbol->symbol_value;
3673
3674       /* For executables we will have to use the symbol's address and
3675          find out what section would contain that address.   Yuk.  */
3676       for (section = abfd->sections; section; section = section->next)
3677         {
3678           if (value >= section->vma
3679               && value <= section->vma + section->_cooked_size)
3680             return section;
3681         }
3682
3683       /* Should never happen.  */
3684       abort ();
3685     }
3686 }
3687
3688 /* Read and save the symbol table associated with the given BFD.  */
3689
3690 static unsigned int
3691 som_slurp_symbol_table (abfd)
3692      bfd *abfd;
3693 {
3694   int symbol_count = bfd_get_symcount (abfd);
3695   int symsize = sizeof (struct symbol_dictionary_record);
3696   char *stringtab;
3697   struct symbol_dictionary_record *buf = NULL, *bufp, *endbufp;
3698   som_symbol_type *sym, *symbase;
3699
3700   /* Return saved value if it exists.  */
3701   if (obj_som_symtab (abfd) != NULL)
3702     goto successful_return;
3703
3704   /* Special case.  This is *not* an error.  */
3705   if (symbol_count == 0)
3706     goto successful_return;
3707
3708   if (!som_slurp_string_table (abfd))
3709     goto error_return;
3710
3711   stringtab = obj_som_stringtab (abfd);
3712
3713   symbase = (som_symbol_type *)
3714     malloc (symbol_count * sizeof (som_symbol_type));
3715   if (symbase == NULL)
3716     {
3717       bfd_set_error (bfd_error_no_memory);
3718       goto error_return;
3719     }
3720
3721   /* Read in the external SOM representation.  */
3722   buf = malloc (symbol_count * symsize);
3723   if (buf == NULL && symbol_count * symsize != 0)
3724     {
3725       bfd_set_error (bfd_error_no_memory);
3726       goto error_return;
3727     }
3728   if (bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET) < 0)
3729     goto error_return;
3730   if (bfd_read (buf, symbol_count * symsize, 1, abfd) 
3731       != symbol_count * symsize)
3732     goto error_return;
3733
3734   /* Iterate over all the symbols and internalize them.  */
3735   endbufp = buf + symbol_count;
3736   for (bufp = buf, sym = symbase; bufp < endbufp; ++bufp)
3737     {
3738
3739       /* I don't think we care about these.  */
3740       if (bufp->symbol_type == ST_SYM_EXT
3741           || bufp->symbol_type == ST_ARG_EXT)
3742         continue;
3743
3744       /* Set some private data we care about.  */
3745       if (bufp->symbol_type == ST_NULL)
3746         som_symbol_data (sym)->som_type = SYMBOL_TYPE_UNKNOWN;
3747       else if (bufp->symbol_type == ST_ABSOLUTE)
3748         som_symbol_data (sym)->som_type = SYMBOL_TYPE_ABSOLUTE;
3749       else if (bufp->symbol_type == ST_DATA)
3750         som_symbol_data (sym)->som_type = SYMBOL_TYPE_DATA;
3751       else if (bufp->symbol_type == ST_CODE)
3752         som_symbol_data (sym)->som_type = SYMBOL_TYPE_CODE;
3753       else if (bufp->symbol_type == ST_PRI_PROG)
3754         som_symbol_data (sym)->som_type = SYMBOL_TYPE_PRI_PROG;
3755       else if (bufp->symbol_type == ST_SEC_PROG)
3756         som_symbol_data (sym)->som_type = SYMBOL_TYPE_SEC_PROG;
3757       else if (bufp->symbol_type == ST_ENTRY)
3758         som_symbol_data (sym)->som_type = SYMBOL_TYPE_ENTRY;
3759       else if (bufp->symbol_type == ST_MILLICODE)
3760         som_symbol_data (sym)->som_type = SYMBOL_TYPE_MILLICODE;
3761       else if (bufp->symbol_type == ST_PLABEL)
3762         som_symbol_data (sym)->som_type = SYMBOL_TYPE_PLABEL;
3763       else
3764         som_symbol_data (sym)->som_type = SYMBOL_TYPE_UNKNOWN;
3765       som_symbol_data (sym)->tc_data.hppa_arg_reloc = bufp->arg_reloc;
3766
3767       /* Some reasonable defaults.  */
3768       sym->symbol.the_bfd = abfd;
3769       sym->symbol.name = bufp->name.n_strx + stringtab;
3770       sym->symbol.value = bufp->symbol_value;
3771       sym->symbol.section = 0;
3772       sym->symbol.flags = 0;
3773
3774       switch (bufp->symbol_type)
3775         {
3776         case ST_ENTRY:
3777         case ST_PRI_PROG:
3778         case ST_SEC_PROG:
3779         case ST_MILLICODE:
3780           sym->symbol.flags |= BSF_FUNCTION;
3781           sym->symbol.value &= ~0x3;
3782           break;
3783
3784         case ST_STUB:
3785         case ST_CODE:
3786           sym->symbol.value &= ~0x3;
3787           /* If the symbol's scope is ST_UNSAT, then these are
3788              undefined function symbols.  */
3789           if (bufp->symbol_scope == SS_UNSAT)
3790             sym->symbol.flags |= BSF_FUNCTION;
3791              
3792
3793         default:
3794           break;
3795         }
3796
3797       /* Handle scoping and section information.  */
3798       switch (bufp->symbol_scope)
3799         {
3800         /* symbol_info field is undefined for SS_EXTERNAL and SS_UNSAT symbols,
3801            so the section associated with this symbol can't be known.  */
3802         case SS_EXTERNAL:
3803           if (bufp->symbol_type != ST_STORAGE)
3804             sym->symbol.section = bfd_und_section_ptr;
3805           else
3806             sym->symbol.section = bfd_com_section_ptr;
3807           sym->symbol.flags |= (BSF_EXPORT | BSF_GLOBAL);
3808           break;
3809
3810         case SS_UNSAT:
3811           if (bufp->symbol_type != ST_STORAGE)
3812             sym->symbol.section = bfd_und_section_ptr;
3813           else
3814             sym->symbol.section = bfd_com_section_ptr;
3815           break;
3816
3817         case SS_UNIVERSAL:
3818           sym->symbol.flags |= (BSF_EXPORT | BSF_GLOBAL);
3819           sym->symbol.section = bfd_section_from_som_symbol (abfd, bufp);
3820           sym->symbol.value -= sym->symbol.section->vma;
3821           break;
3822
3823 #if 0
3824         /* SS_GLOBAL and SS_LOCAL are two names for the same thing.
3825            Sound dumb?  It is.  */
3826         case SS_GLOBAL:
3827 #endif
3828         case SS_LOCAL:
3829           sym->symbol.flags |= BSF_LOCAL;
3830           sym->symbol.section = bfd_section_from_som_symbol (abfd, bufp);
3831           sym->symbol.value -= sym->symbol.section->vma;
3832           break;
3833         }
3834
3835       /* Mark section symbols and symbols used by the debugger.  */
3836       if (sym->symbol.name[0] == '$'
3837           && sym->symbol.name[strlen (sym->symbol.name) - 1] == '$')
3838         sym->symbol.flags |= BSF_SECTION_SYM;
3839       else if (!strncmp (sym->symbol.name, "L$0\002", 4))
3840         {
3841           sym->symbol.flags |= BSF_SECTION_SYM;
3842           sym->symbol.name = sym->symbol.section->name;
3843         }
3844       else if (!strncmp (sym->symbol.name, "L$0\001", 4))
3845         sym->symbol.flags |= BSF_DEBUGGING;
3846
3847       /* Note increment at bottom of loop, since we skip some symbols
3848          we can not include it as part of the for statement.  */
3849       sym++;
3850     }
3851
3852   /* Save our results and return success.  */
3853   obj_som_symtab (abfd) = symbase;
3854  successful_return:
3855   if (buf != NULL)
3856     free (buf);
3857   return (true);
3858
3859  error_return:
3860   if (buf != NULL)
3861     free (buf);
3862   return false;
3863 }
3864
3865 /* Canonicalize a SOM symbol table.  Return the number of entries
3866    in the symbol table.  */
3867
3868 static long
3869 som_get_symtab (abfd, location)
3870      bfd *abfd;
3871      asymbol **location;
3872 {
3873   int i;
3874   som_symbol_type *symbase;
3875
3876   if (!som_slurp_symbol_table (abfd))
3877     return -1;
3878
3879   i = bfd_get_symcount (abfd);
3880   symbase = obj_som_symtab (abfd);
3881
3882   for (; i > 0; i--, location++, symbase++)
3883     *location = &symbase->symbol;
3884
3885   /* Final null pointer.  */
3886   *location = 0;
3887   return (bfd_get_symcount (abfd));
3888 }
3889
3890 /* Make a SOM symbol.  There is nothing special to do here.  */
3891
3892 static asymbol *
3893 som_make_empty_symbol (abfd)
3894      bfd *abfd;
3895 {
3896   som_symbol_type *new =
3897   (som_symbol_type *) bfd_zalloc (abfd, sizeof (som_symbol_type));
3898   if (new == NULL)
3899     {
3900       bfd_set_error (bfd_error_no_memory);
3901       return 0;
3902     }
3903   new->symbol.the_bfd = abfd;
3904
3905   return &new->symbol;
3906 }
3907
3908 /* Print symbol information.  */
3909
3910 static void
3911 som_print_symbol (ignore_abfd, afile, symbol, how)
3912      bfd *ignore_abfd;
3913      PTR afile;
3914      asymbol *symbol;
3915      bfd_print_symbol_type how;
3916 {
3917   FILE *file = (FILE *) afile;
3918   switch (how)
3919     {
3920     case bfd_print_symbol_name:
3921       fprintf (file, "%s", symbol->name);
3922       break;
3923     case bfd_print_symbol_more:
3924       fprintf (file, "som ");
3925       fprintf_vma (file, symbol->value);
3926       fprintf (file, " %lx", (long) symbol->flags);
3927       break;
3928     case bfd_print_symbol_all:
3929       {
3930         CONST char *section_name;
3931         section_name = symbol->section ? symbol->section->name : "(*none*)";
3932         bfd_print_symbol_vandf ((PTR) file, symbol);
3933         fprintf (file, " %s\t%s", section_name, symbol->name);
3934         break;
3935       }
3936     }
3937 }
3938
3939 static boolean
3940 som_bfd_is_local_label (abfd, sym)
3941      bfd *abfd;
3942      asymbol *sym;
3943 {
3944   return (sym->name[0] == 'L' && sym->name[1] == '$');
3945 }
3946
3947 /* Count or process variable-length SOM fixup records.
3948
3949    To avoid code duplication we use this code both to compute the number
3950    of relocations requested by a stream, and to internalize the stream.
3951
3952    When computing the number of relocations requested by a stream the
3953    variables rptr, section, and symbols have no meaning.
3954
3955    Return the number of relocations requested by the fixup stream.  When
3956    not just counting 
3957
3958    This needs at least two or three more passes to get it cleaned up.  */
3959
3960 static unsigned int
3961 som_set_reloc_info (fixup, end, internal_relocs, section, symbols, just_count)
3962      unsigned char *fixup;
3963      unsigned int end;
3964      arelent *internal_relocs;
3965      asection *section;
3966      asymbol **symbols;
3967      boolean just_count;
3968 {
3969   unsigned int op, varname;
3970   unsigned char *end_fixups = &fixup[end];
3971   const struct fixup_format *fp;
3972   char *cp;
3973   unsigned char *save_fixup;
3974   int variables[26], stack[20], c, v, count, prev_fixup, *sp;
3975   const int *subop;
3976   arelent *rptr= internal_relocs;
3977   unsigned int offset = 0;
3978
3979 #define var(c)          variables[(c) - 'A']
3980 #define push(v)         (*sp++ = (v))
3981 #define pop()           (*--sp)
3982 #define emptystack()    (sp == stack)
3983
3984   som_initialize_reloc_queue (reloc_queue);
3985   memset (variables, 0, sizeof (variables));
3986   memset (stack, 0, sizeof (stack));
3987   count = 0;
3988   prev_fixup = 0;
3989   sp = stack;
3990
3991   while (fixup < end_fixups)
3992     {
3993
3994       /* Save pointer to the start of this fixup.  We'll use
3995          it later to determine if it is necessary to put this fixup
3996          on the queue.  */
3997       save_fixup = fixup;
3998
3999       /* Get the fixup code and its associated format.  */
4000       op = *fixup++;
4001       fp = &som_fixup_formats[op];
4002
4003       /* Handle a request for a previous fixup.  */
4004       if (*fp->format == 'P')
4005         {
4006           /* Get pointer to the beginning of the prev fixup, move
4007              the repeated fixup to the head of the queue.  */
4008           fixup = reloc_queue[fp->D].reloc;
4009           som_reloc_queue_fix (reloc_queue, fp->D);
4010           prev_fixup = 1;
4011
4012           /* Get the fixup code and its associated format.  */
4013           op = *fixup++;
4014           fp = &som_fixup_formats[op];
4015         }
4016
4017       /* If this fixup will be passed to BFD, set some reasonable defaults.  */
4018       if (! just_count
4019           && som_hppa_howto_table[op].type != R_NO_RELOCATION
4020           && som_hppa_howto_table[op].type != R_DATA_OVERRIDE)
4021         {
4022           rptr->address = offset;
4023           rptr->howto = &som_hppa_howto_table[op];
4024           rptr->addend = 0;
4025           rptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
4026         }
4027
4028       /* Set default input length to 0.  Get the opcode class index
4029          into D.  */
4030       var ('L') = 0;
4031       var ('D') = fp->D;
4032
4033       /* Get the opcode format.  */
4034       cp = fp->format;
4035
4036       /* Process the format string.  Parsing happens in two phases,
4037          parse RHS, then assign to LHS.  Repeat until no more 
4038          characters in the format string.  */
4039       while (*cp)
4040         {
4041           /* The variable this pass is going to compute a value for.  */
4042           varname = *cp++;
4043
4044           /* Start processing RHS.  Continue until a NULL or '=' is found.  */
4045           do
4046             {
4047               c = *cp++;
4048
4049               /* If this is a variable, push it on the stack.  */
4050               if (isupper (c))
4051                 push (var (c));
4052
4053               /* If this is a lower case letter, then it represents
4054                  additional data from the fixup stream to be pushed onto
4055                  the stack.  */
4056               else if (islower (c))
4057                 {
4058                   for (v = 0; c > 'a'; --c)
4059                     v = (v << 8) | *fixup++;
4060                   push (v);
4061                 }
4062
4063               /* A decimal constant.  Push it on the stack.  */
4064               else if (isdigit (c))
4065                 {
4066                   v = c - '0';
4067                   while (isdigit (*cp))
4068                     v = (v * 10) + (*cp++ - '0');
4069                   push (v);
4070                 }
4071               else
4072
4073                 /* An operator.  Pop two two values from the stack and
4074                    use them as operands to the given operation.  Push
4075                    the result of the operation back on the stack.  */
4076                 switch (c)
4077                   {
4078                   case '+':
4079                     v = pop ();
4080                     v += pop ();
4081                     push (v);
4082                     break;
4083                   case '*':
4084                     v = pop ();
4085                     v *= pop ();
4086                     push (v);
4087                     break;
4088                   case '<':
4089                     v = pop ();
4090                     v = pop () << v;
4091                     push (v);
4092                     break;
4093                   default:
4094                     abort ();
4095                   }
4096             }
4097           while (*cp && *cp != '=');
4098
4099           /* Move over the equal operator.  */
4100           cp++;
4101
4102           /* Pop the RHS off the stack.  */
4103           c = pop ();
4104
4105           /* Perform the assignment.  */
4106           var (varname) = c;
4107
4108           /* Handle side effects. and special 'O' stack cases.  */
4109           switch (varname)
4110             {
4111             /* Consume some bytes from the input space.  */
4112             case 'L':
4113               offset += c;
4114               break;
4115             /* A symbol to use in the relocation.  Make a note
4116                of this if we are not just counting.  */
4117             case 'S':
4118               if (! just_count)
4119                 rptr->sym_ptr_ptr = &symbols[c];
4120               break;
4121             /* Handle the linker expression stack.  */
4122             case 'O':
4123               switch (op)
4124                 {
4125                 case R_COMP1:
4126                   subop = comp1_opcodes;
4127                   break;
4128                 case R_COMP2:
4129                   subop = comp2_opcodes;
4130                   break;
4131                 case R_COMP3:
4132                   subop = comp3_opcodes;
4133                   break;
4134                 default:
4135                   abort ();
4136                 }
4137               while (*subop <= (unsigned char) c)
4138                 ++subop;
4139               --subop;
4140               break;
4141             default:
4142               break;
4143             }
4144         }
4145
4146       /* If we used a previous fixup, clean up after it.  */
4147       if (prev_fixup)
4148         {
4149           fixup = save_fixup + 1;
4150           prev_fixup = 0;
4151         }
4152       /* Queue it.  */
4153       else if (fixup > save_fixup + 1)
4154         som_reloc_queue_insert (save_fixup, fixup - save_fixup, reloc_queue);
4155
4156       /* We do not pass R_DATA_OVERRIDE or R_NO_RELOCATION 
4157          fixups to BFD.  */
4158       if (som_hppa_howto_table[op].type != R_DATA_OVERRIDE
4159           && som_hppa_howto_table[op].type != R_NO_RELOCATION)
4160         {
4161           /* Done with a single reloction. Loop back to the top.  */
4162           if (! just_count)
4163             {
4164               rptr->addend = var ('V');
4165               rptr++;
4166             }
4167           count++;
4168           /* Now that we've handled a "full" relocation, reset
4169              some state.  */
4170           memset (variables, 0, sizeof (variables));
4171           memset (stack, 0, sizeof (stack));
4172         }
4173     }
4174   return count;
4175
4176 #undef var
4177 #undef push
4178 #undef pop
4179 #undef emptystack
4180 }
4181
4182 /* Read in the relocs (aka fixups in SOM terms) for a section. 
4183
4184    som_get_reloc_upper_bound calls this routine with JUST_COUNT 
4185    set to true to indicate it only needs a count of the number
4186    of actual relocations.  */
4187
4188 static boolean
4189 som_slurp_reloc_table (abfd, section, symbols, just_count)
4190      bfd *abfd;
4191      asection *section;
4192      asymbol **symbols;
4193      boolean just_count;
4194 {
4195   char *external_relocs;
4196   unsigned int fixup_stream_size;
4197   arelent *internal_relocs;
4198   unsigned int num_relocs;
4199
4200   fixup_stream_size = som_section_data (section)->reloc_size;
4201   /* If there were no relocations, then there is nothing to do.  */
4202   if (section->reloc_count == 0)
4203     return true;
4204
4205   /* If reloc_count is -1, then the relocation stream has not been 
4206      parsed.  We must do so now to know how many relocations exist.  */
4207   if (section->reloc_count == -1)
4208     {
4209       external_relocs = (char *) malloc (fixup_stream_size);
4210       if (external_relocs == (char *) NULL)
4211         {
4212           bfd_set_error (bfd_error_no_memory);
4213           return false;
4214         }
4215       /* Read in the external forms. */
4216       if (bfd_seek (abfd,
4217                     obj_som_reloc_filepos (abfd) + section->rel_filepos,
4218                     SEEK_SET)
4219           != 0)
4220         return false;
4221       if (bfd_read (external_relocs, 1, fixup_stream_size, abfd)
4222           != fixup_stream_size)
4223         return false;
4224
4225       /* Let callers know how many relocations found.
4226          also save the relocation stream as we will
4227          need it again.  */
4228       section->reloc_count = som_set_reloc_info (external_relocs,
4229                                                  fixup_stream_size,
4230                                                  NULL, NULL, NULL, true);
4231
4232       som_section_data (section)->reloc_stream = external_relocs;
4233     }
4234
4235   /* If the caller only wanted a count, then return now.  */
4236   if (just_count)
4237     return true;
4238
4239   num_relocs = section->reloc_count;
4240   external_relocs = som_section_data (section)->reloc_stream;
4241   /* Return saved information about the relocations if it is available.  */
4242   if (section->relocation != (arelent *) NULL)
4243     return true;
4244
4245   internal_relocs = (arelent *) malloc (num_relocs * sizeof (arelent));
4246   if (internal_relocs == (arelent *) NULL)
4247     {
4248       bfd_set_error (bfd_error_no_memory);
4249       return false;
4250     }
4251
4252   /* Process and internalize the relocations.  */
4253   som_set_reloc_info (external_relocs, fixup_stream_size,
4254                       internal_relocs, section, symbols, false);
4255
4256   /* Save our results and return success.  */
4257   section->relocation = internal_relocs;
4258   return (true);
4259 }
4260
4261 /* Return the number of bytes required to store the relocation
4262    information associated with the given section.  */ 
4263
4264 static long
4265 som_get_reloc_upper_bound (abfd, asect)
4266      bfd *abfd;
4267      sec_ptr asect;
4268 {
4269   /* If section has relocations, then read in the relocation stream
4270      and parse it to determine how many relocations exist.  */
4271   if (asect->flags & SEC_RELOC)
4272     {
4273       if (! som_slurp_reloc_table (abfd, asect, NULL, true))
4274         return false;
4275       return (asect->reloc_count + 1) * sizeof (arelent);
4276     }
4277   /* There are no relocations.  */
4278   return 0;
4279 }
4280
4281 /* Convert relocations from SOM (external) form into BFD internal
4282    form.  Return the number of relocations.  */
4283
4284 static long
4285 som_canonicalize_reloc (abfd, section, relptr, symbols)
4286      bfd *abfd;
4287      sec_ptr section;
4288      arelent **relptr;
4289      asymbol **symbols;
4290 {
4291   arelent *tblptr;
4292   int count;
4293
4294   if (som_slurp_reloc_table (abfd, section, symbols, false) == false)
4295     return -1;
4296
4297   count = section->reloc_count;
4298   tblptr = section->relocation;
4299
4300   while (count--)
4301     *relptr++ = tblptr++;
4302
4303   *relptr = (arelent *) NULL;
4304   return section->reloc_count;
4305 }
4306
4307 extern const bfd_target som_vec;
4308
4309 /* A hook to set up object file dependent section information.  */
4310
4311 static boolean
4312 som_new_section_hook (abfd, newsect)
4313      bfd *abfd;
4314      asection *newsect;
4315 {
4316   newsect->used_by_bfd =
4317     (PTR) bfd_zalloc (abfd, sizeof (struct som_section_data_struct));
4318   if (!newsect->used_by_bfd)
4319     {
4320       bfd_set_error (bfd_error_no_memory);
4321       return false;
4322     }
4323   newsect->alignment_power = 3;
4324
4325   /* We allow more than three sections internally */
4326   return true;
4327 }
4328
4329 /* Copy any private info we understand from the input section
4330    to the output section.  */
4331 static boolean
4332 som_bfd_copy_private_section_data (ibfd, isection, obfd, osection)
4333      bfd *ibfd;
4334      asection *isection;
4335      bfd *obfd;
4336      asection *osection;
4337 {
4338   /* One day we may try to grok other private data.  */
4339   if (ibfd->xvec->flavour != bfd_target_som_flavour
4340       || obfd->xvec->flavour != bfd_target_som_flavour
4341       || (!som_is_space (isection) && !som_is_subspace (isection)))
4342     return false;
4343
4344   som_section_data (osection)->copy_data
4345     = (struct som_copyable_section_data_struct *)
4346       bfd_zalloc (obfd, sizeof (struct som_copyable_section_data_struct));
4347   if (som_section_data (osection)->copy_data == NULL)
4348     {
4349       bfd_set_error (bfd_error_no_memory);
4350       return false;
4351     }
4352
4353   memcpy (som_section_data (osection)->copy_data,
4354           som_section_data (isection)->copy_data,
4355           sizeof (struct som_copyable_section_data_struct));
4356
4357   /* Reparent if necessary.  */
4358   if (som_section_data (osection)->copy_data->container)
4359     som_section_data (osection)->copy_data->container =
4360       som_section_data (osection)->copy_data->container->output_section;
4361
4362   return true;
4363 }
4364
4365 /* Copy any private info we understand from the input bfd
4366    to the output bfd.  */
4367
4368 static boolean
4369 som_bfd_copy_private_bfd_data (ibfd, obfd)
4370      bfd *ibfd, *obfd;
4371 {
4372   /* One day we may try to grok other private data.  */
4373   if (ibfd->xvec->flavour != bfd_target_som_flavour
4374       || obfd->xvec->flavour != bfd_target_som_flavour)
4375     return false;
4376
4377   /* Allocate some memory to hold the data we need.  */
4378   obj_som_exec_data (obfd) = (struct som_exec_data *)
4379     bfd_zalloc (obfd, sizeof (struct som_exec_data));
4380   if (obj_som_exec_data (obfd) == NULL)
4381     {
4382       bfd_set_error (bfd_error_no_memory);
4383       return false;
4384     }
4385
4386   /* Now copy the data.  */
4387   memcpy (obj_som_exec_data (obfd), obj_som_exec_data (ibfd),
4388           sizeof (struct som_exec_data));
4389
4390   return true;
4391 }
4392
4393 /* Set backend info for sections which can not be described
4394    in the BFD data structures.  */
4395
4396 boolean
4397 bfd_som_set_section_attributes (section, defined, private, sort_key, spnum)
4398      asection *section;
4399      int defined;
4400      int private;
4401      unsigned int sort_key;
4402      int spnum;
4403 {
4404   /* Allocate memory to hold the magic information.  */
4405   if (som_section_data (section)->copy_data == NULL)
4406     {
4407       som_section_data (section)->copy_data
4408         = (struct som_copyable_section_data_struct *)
4409           bfd_zalloc (section->owner,
4410                       sizeof (struct som_copyable_section_data_struct));
4411       if (som_section_data (section)->copy_data == NULL)
4412         {
4413           bfd_set_error (bfd_error_no_memory);
4414           return false;
4415         }
4416     }
4417   som_section_data (section)->copy_data->sort_key = sort_key;
4418   som_section_data (section)->copy_data->is_defined = defined;
4419   som_section_data (section)->copy_data->is_private = private;
4420   som_section_data (section)->copy_data->container = section;
4421   som_section_data (section)->copy_data->space_number = spnum;
4422   return true;
4423 }
4424
4425 /* Set backend info for subsections which can not be described 
4426    in the BFD data structures.  */
4427
4428 boolean
4429 bfd_som_set_subsection_attributes (section, container, access,
4430                                    sort_key, quadrant)
4431      asection *section;
4432      asection *container;
4433      int access;
4434      unsigned int sort_key;
4435      int quadrant;
4436 {
4437   /* Allocate memory to hold the magic information.  */
4438   if (som_section_data (section)->copy_data == NULL)
4439     {
4440       som_section_data (section)->copy_data
4441         = (struct som_copyable_section_data_struct *)
4442           bfd_zalloc (section->owner,
4443                       sizeof (struct som_copyable_section_data_struct));
4444       if (som_section_data (section)->copy_data == NULL)
4445         {
4446           bfd_set_error (bfd_error_no_memory);
4447           return false;
4448         }
4449     }
4450   som_section_data (section)->copy_data->sort_key = sort_key;
4451   som_section_data (section)->copy_data->access_control_bits = access;
4452   som_section_data (section)->copy_data->quadrant = quadrant;
4453   som_section_data (section)->copy_data->container = container;
4454   return true;
4455 }
4456
4457 /* Set the full SOM symbol type.  SOM needs far more symbol information
4458    than any other object file format I'm aware of.  It is mandatory
4459    to be able to know if a symbol is an entry point, millicode, data,
4460    code, absolute, storage request, or procedure label.  If you get
4461    the symbol type wrong your program will not link.  */
4462
4463 void
4464 bfd_som_set_symbol_type (symbol, type)
4465      asymbol *symbol;
4466      unsigned int type;
4467 {
4468   som_symbol_data (symbol)->som_type = type;
4469 }
4470
4471 /* Attach 64bits of unwind information to a symbol (which hopefully
4472    is a function of some kind!).  It would be better to keep this
4473    in the R_ENTRY relocation, but there is not enough space.  */
4474
4475 void
4476 bfd_som_attach_unwind_info (symbol, unwind_desc)
4477      asymbol *symbol;
4478      char *unwind_desc;
4479 {
4480   som_symbol_data (symbol)->unwind = unwind_desc;
4481 }
4482
4483 /* Attach an auxiliary header to the BFD backend so that it may be
4484    written into the object file.  */
4485 boolean
4486 bfd_som_attach_aux_hdr (abfd, type, string)
4487      bfd *abfd;
4488      int type;
4489      char *string;
4490 {
4491   if (type == VERSION_AUX_ID)
4492     {
4493       int len = strlen (string);
4494       int pad = 0;
4495
4496       if (len % 4)
4497         pad = (4 - (len % 4));
4498       obj_som_version_hdr (abfd) = (struct user_string_aux_hdr *)
4499         bfd_zalloc (abfd, sizeof (struct aux_id)
4500                               + sizeof (unsigned int) + len + pad);
4501       if (!obj_som_version_hdr (abfd))
4502         {
4503           bfd_set_error (bfd_error_no_memory);
4504           return false;
4505         }
4506       obj_som_version_hdr (abfd)->header_id.type = VERSION_AUX_ID;
4507       obj_som_version_hdr (abfd)->header_id.length = len + pad;
4508       obj_som_version_hdr (abfd)->header_id.length += sizeof (int);
4509       obj_som_version_hdr (abfd)->string_length = len;
4510       strncpy (obj_som_version_hdr (abfd)->user_string, string, len);
4511     }
4512   else if (type == COPYRIGHT_AUX_ID)
4513     {
4514       int len = strlen (string);
4515       int pad = 0;
4516
4517       if (len % 4)
4518         pad = (4 - (len % 4));
4519       obj_som_copyright_hdr (abfd) = (struct copyright_aux_hdr *)
4520         bfd_zalloc (abfd, sizeof (struct aux_id)
4521                             + sizeof (unsigned int) + len + pad);
4522       if (!obj_som_copyright_hdr (abfd))
4523         {
4524           bfd_set_error (bfd_error_no_memory);
4525           return false;
4526         }
4527       obj_som_copyright_hdr (abfd)->header_id.type = COPYRIGHT_AUX_ID;
4528       obj_som_copyright_hdr (abfd)->header_id.length = len + pad;
4529       obj_som_copyright_hdr (abfd)->header_id.length += sizeof (int);
4530       obj_som_copyright_hdr (abfd)->string_length = len;
4531       strcpy (obj_som_copyright_hdr (abfd)->copyright, string);
4532     }
4533   return true;
4534 }
4535
4536 static boolean
4537 som_get_section_contents (abfd, section, location, offset, count)
4538      bfd *abfd;
4539      sec_ptr section;
4540      PTR location;
4541      file_ptr offset;
4542      bfd_size_type count;
4543 {
4544   if (count == 0 || ((section->flags & (SEC_LOAD | SEC_DEBUGGING)) == 0))
4545     return true;
4546   if ((bfd_size_type)(offset+count) > section->_raw_size
4547       || bfd_seek (abfd, (file_ptr)(section->filepos + offset), SEEK_SET) == -1
4548       || bfd_read (location, (bfd_size_type)1, count, abfd) != count)
4549     return (false); /* on error */
4550   return (true);
4551 }
4552
4553 static boolean
4554 som_set_section_contents (abfd, section, location, offset, count)
4555      bfd *abfd;
4556      sec_ptr section;
4557      PTR location;
4558      file_ptr offset;
4559      bfd_size_type count;
4560 {
4561   if (abfd->output_has_begun == false)
4562     {
4563       /* Set up fixed parts of the file, space, and subspace headers.
4564          Notify the world that output has begun.  */
4565       som_prep_headers (abfd);
4566       abfd->output_has_begun = true;
4567       /* Start writing the object file.  This include all the string
4568          tables, fixup streams, and other portions of the object file.  */
4569       som_begin_writing (abfd);
4570     }
4571
4572   /* Only write subspaces which have "real" contents (eg. the contents
4573      are not generated at run time by the OS).  */
4574   if (!som_is_subspace (section)
4575       || ((section->flags & (SEC_LOAD | SEC_DEBUGGING)) == 0))
4576     return true;
4577
4578   /* Seek to the proper offset within the object file and write the
4579      data.  */
4580   offset += som_section_data (section)->subspace_dict->file_loc_init_value; 
4581   if (bfd_seek (abfd, offset, SEEK_SET) == -1)
4582     return false;
4583
4584   if (bfd_write ((PTR) location, 1, count, abfd) != count)
4585     return false;
4586   return true;
4587 }
4588
4589 static boolean
4590 som_set_arch_mach (abfd, arch, machine)
4591      bfd *abfd;
4592      enum bfd_architecture arch;
4593      unsigned long machine;
4594 {
4595   /* Allow any architecture to be supported by the SOM backend */
4596   return bfd_default_set_arch_mach (abfd, arch, machine);
4597 }
4598
4599 static boolean
4600 som_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
4601                         functionname_ptr, line_ptr)
4602      bfd *abfd;
4603      asection *section;
4604      asymbol **symbols;
4605      bfd_vma offset;
4606      CONST char **filename_ptr;
4607      CONST char **functionname_ptr;
4608      unsigned int *line_ptr;
4609 {
4610   fprintf (stderr, "som_find_nearest_line unimplemented\n");
4611   fflush (stderr);
4612   abort ();
4613   return (false);
4614 }
4615
4616 static int
4617 som_sizeof_headers (abfd, reloc)
4618      bfd *abfd;
4619      boolean reloc;
4620 {
4621   fprintf (stderr, "som_sizeof_headers unimplemented\n");
4622   fflush (stderr);
4623   abort ();
4624   return (0);
4625 }
4626
4627 /* Return the single-character symbol type corresponding to
4628    SOM section S, or '?' for an unknown SOM section.  */
4629
4630 static char
4631 som_section_type (s)
4632      const char *s;
4633 {
4634   const struct section_to_type *t;
4635
4636   for (t = &stt[0]; t->section; t++)
4637     if (!strcmp (s, t->section))
4638       return t->type;
4639   return '?';
4640 }
4641
4642 static int
4643 som_decode_symclass (symbol)
4644      asymbol *symbol;
4645 {
4646   char c;
4647
4648   if (bfd_is_com_section (symbol->section))
4649     return 'C';
4650   if (bfd_is_und_section (symbol->section))
4651     return 'U';
4652   if (bfd_is_ind_section (symbol->section))
4653     return 'I';
4654   if (!(symbol->flags & (BSF_GLOBAL|BSF_LOCAL)))
4655     return '?';
4656
4657   if (bfd_is_abs_section (symbol->section))
4658     c = 'a';
4659   else if (symbol->section)
4660     c = som_section_type (symbol->section->name);
4661   else
4662     return '?';
4663   if (symbol->flags & BSF_GLOBAL)
4664     c = toupper (c);
4665   return c;
4666 }
4667
4668 /* Return information about SOM symbol SYMBOL in RET.  */
4669
4670 static void
4671 som_get_symbol_info (ignore_abfd, symbol, ret)
4672      bfd *ignore_abfd;
4673      asymbol *symbol;
4674      symbol_info *ret;
4675 {
4676   ret->type = som_decode_symclass (symbol);
4677   if (ret->type != 'U')
4678     ret->value = symbol->value+symbol->section->vma;
4679   else
4680     ret->value = 0;
4681   ret->name = symbol->name;
4682 }
4683
4684 /* Count the number of symbols in the archive symbol table.  Necessary
4685    so that we can allocate space for all the carsyms at once.  */
4686
4687 static boolean
4688 som_bfd_count_ar_symbols (abfd, lst_header, count)
4689      bfd *abfd;
4690      struct lst_header *lst_header;
4691      symindex *count;
4692 {
4693   unsigned int i;
4694   unsigned int *hash_table = NULL;
4695   file_ptr lst_filepos = bfd_tell (abfd) - sizeof (struct lst_header);
4696
4697   hash_table = 
4698     (unsigned int *) malloc (lst_header->hash_size * sizeof (unsigned int));
4699   if (hash_table == NULL && lst_header->hash_size != 0)
4700     {
4701       bfd_set_error (bfd_error_no_memory);
4702       goto error_return;
4703     }
4704
4705   /* Don't forget to initialize the counter!  */
4706   *count = 0;
4707
4708   /* Read in the hash table.  The has table is an array of 32bit file offsets
4709      which point to the hash chains.  */
4710   if (bfd_read ((PTR) hash_table, lst_header->hash_size, 4, abfd)
4711       != lst_header->hash_size * 4)
4712     goto error_return;
4713
4714   /* Walk each chain counting the number of symbols found on that particular
4715      chain.  */
4716   for (i = 0; i < lst_header->hash_size; i++)
4717     {
4718       struct lst_symbol_record lst_symbol;
4719
4720       /* An empty chain has zero as it's file offset.  */
4721       if (hash_table[i] == 0)
4722         continue;
4723
4724       /* Seek to the first symbol in this hash chain.  */
4725       if (bfd_seek (abfd, lst_filepos + hash_table[i], SEEK_SET) < 0)
4726         goto error_return;
4727
4728       /* Read in this symbol and update the counter.  */
4729       if (bfd_read ((PTR) & lst_symbol, 1, sizeof (lst_symbol), abfd)
4730           != sizeof (lst_symbol))
4731         goto error_return;
4732
4733       (*count)++;
4734
4735       /* Now iterate through the rest of the symbols on this chain.  */
4736       while (lst_symbol.next_entry)
4737         {
4738
4739           /* Seek to the next symbol.  */
4740           if (bfd_seek (abfd, lst_filepos + lst_symbol.next_entry, SEEK_SET)
4741               < 0)
4742             goto error_return;
4743
4744           /* Read the symbol in and update the counter.  */
4745           if (bfd_read ((PTR) & lst_symbol, 1, sizeof (lst_symbol), abfd)
4746               != sizeof (lst_symbol))
4747             goto error_return;
4748
4749           (*count)++;
4750         }
4751     }
4752   if (hash_table != NULL)
4753     free (hash_table);
4754   return true;
4755
4756  error_return:
4757   if (hash_table != NULL)
4758     free (hash_table);
4759   return false;
4760 }
4761
4762 /* Fill in the canonical archive symbols (SYMS) from the archive described
4763    by ABFD and LST_HEADER.  */
4764
4765 static boolean
4766 som_bfd_fill_in_ar_symbols (abfd, lst_header, syms)
4767      bfd *abfd;
4768      struct lst_header *lst_header;
4769      carsym **syms;
4770 {
4771   unsigned int i, len;
4772   carsym *set = syms[0];
4773   unsigned int *hash_table = NULL;
4774   struct som_entry *som_dict = NULL;
4775   file_ptr lst_filepos = bfd_tell (abfd) - sizeof (struct lst_header);
4776
4777   hash_table = 
4778     (unsigned int *) malloc (lst_header->hash_size * sizeof (unsigned int));
4779   if (hash_table == NULL && lst_header->hash_size != 0)
4780     {
4781       bfd_set_error (bfd_error_no_memory);
4782       goto error_return;
4783     }
4784
4785   som_dict =
4786     (struct som_entry *) malloc (lst_header->module_count
4787                                  * sizeof (struct som_entry));
4788   if (som_dict == NULL && lst_header->module_count != 0)
4789     {
4790       bfd_set_error (bfd_error_no_memory);
4791       goto error_return;
4792     }
4793
4794   /* Read in the hash table.  The has table is an array of 32bit file offsets
4795      which point to the hash chains.  */
4796   if (bfd_read ((PTR) hash_table, lst_header->hash_size, 4, abfd)
4797       != lst_header->hash_size * 4)
4798     goto error_return;
4799
4800   /* Seek to and read in the SOM dictionary.  We will need this to fill
4801      in the carsym's filepos field.  */
4802   if (bfd_seek (abfd, lst_filepos + lst_header->dir_loc, SEEK_SET) < 0)
4803     goto error_return;
4804
4805   if (bfd_read ((PTR) som_dict, lst_header->module_count, 
4806                 sizeof (struct som_entry), abfd)
4807       != lst_header->module_count * sizeof (struct som_entry))
4808     goto error_return;
4809
4810   /* Walk each chain filling in the carsyms as we go along.  */
4811   for (i = 0; i < lst_header->hash_size; i++)
4812     {
4813       struct lst_symbol_record lst_symbol;
4814
4815       /* An empty chain has zero as it's file offset.  */
4816       if (hash_table[i] == 0)
4817         continue;
4818
4819       /* Seek to and read the first symbol on the chain.  */
4820       if (bfd_seek (abfd, lst_filepos + hash_table[i], SEEK_SET) < 0)
4821         goto error_return;
4822
4823       if (bfd_read ((PTR) & lst_symbol, 1, sizeof (lst_symbol), abfd)
4824           != sizeof (lst_symbol))
4825         goto error_return;
4826
4827       /* Get the name of the symbol, first get the length which is stored
4828          as a 32bit integer just before the symbol.
4829
4830          One might ask why we don't just read in the entire string table
4831          and index into it.  Well, according to the SOM ABI the string
4832          index can point *anywhere* in the archive to save space, so just
4833          using the string table would not be safe.  */
4834       if (bfd_seek (abfd, lst_filepos + lst_header->string_loc
4835                             + lst_symbol.name.n_strx - 4, SEEK_SET) < 0)
4836         goto error_return;
4837
4838       if (bfd_read (&len, 1, 4, abfd) != 4)
4839         goto error_return;
4840
4841       /* Allocate space for the name and null terminate it too.  */
4842       set->name = bfd_zalloc (abfd, len + 1);
4843       if (!set->name)
4844         {
4845           bfd_set_error (bfd_error_no_memory);
4846           goto error_return;
4847         }
4848       if (bfd_read (set->name, 1, len, abfd) != len)
4849         goto error_return;
4850
4851       set->name[len] = 0;
4852
4853       /* Fill in the file offset.  Note that the "location" field points
4854          to the SOM itself, not the ar_hdr in front of it.  */
4855       set->file_offset = som_dict[lst_symbol.som_index].location
4856                           - sizeof (struct ar_hdr);
4857
4858       /* Go to the next symbol.  */
4859       set++;
4860
4861       /* Iterate through the rest of the chain.  */
4862       while (lst_symbol.next_entry)
4863         {
4864           /* Seek to the next symbol and read it in.  */
4865           if (bfd_seek (abfd, lst_filepos + lst_symbol.next_entry, SEEK_SET) <0)
4866             goto error_return;
4867
4868           if (bfd_read ((PTR) & lst_symbol, 1, sizeof (lst_symbol), abfd)
4869               != sizeof (lst_symbol))
4870             goto error_return;
4871
4872           /* Seek to the name length & string and read them in.  */
4873           if (bfd_seek (abfd, lst_filepos + lst_header->string_loc 
4874                                 + lst_symbol.name.n_strx - 4, SEEK_SET) < 0)
4875             goto error_return;
4876
4877           if (bfd_read (&len, 1, 4, abfd) != 4)
4878             goto error_return;
4879
4880           /* Allocate space for the name and null terminate it too.  */
4881           set->name = bfd_zalloc (abfd, len + 1);
4882           if (!set->name)
4883             {
4884               bfd_set_error (bfd_error_no_memory);
4885               goto error_return;
4886             }
4887
4888           if (bfd_read (set->name, 1, len, abfd) != len)
4889             goto error_return;
4890           set->name[len] = 0;
4891
4892           /* Fill in the file offset.  Note that the "location" field points
4893              to the SOM itself, not the ar_hdr in front of it.  */
4894           set->file_offset = som_dict[lst_symbol.som_index].location
4895                                - sizeof (struct ar_hdr);
4896
4897           /* Go on to the next symbol.  */
4898           set++;
4899         }
4900     }
4901   /* If we haven't died by now, then we successfully read the entire 
4902      archive symbol table.  */
4903   if (hash_table != NULL)
4904     free (hash_table);
4905   if (som_dict != NULL)
4906     free (som_dict);
4907   return true;
4908
4909  error_return:
4910   if (hash_table != NULL)
4911     free (hash_table);
4912   if (som_dict != NULL)
4913     free (som_dict);
4914   return false;
4915 }
4916
4917 /* Read in the LST from the archive.  */
4918 static boolean
4919 som_slurp_armap (abfd)
4920      bfd *abfd;
4921 {
4922   struct lst_header lst_header;
4923   struct ar_hdr ar_header;
4924   unsigned int parsed_size;
4925   struct artdata *ardata = bfd_ardata (abfd);
4926   char nextname[17];
4927   int i = bfd_read ((PTR) nextname, 1, 16, abfd);
4928
4929   /* Special cases.  */
4930   if (i == 0)
4931     return true;
4932   if (i != 16)
4933     return false;
4934
4935   if (bfd_seek (abfd, (file_ptr) - 16, SEEK_CUR) < 0)
4936     return false;
4937
4938   /* For archives without .o files there is no symbol table.  */
4939   if (strncmp (nextname, "/               ", 16))
4940     {
4941       bfd_has_map (abfd) = false;
4942       return true;
4943     }
4944
4945   /* Read in and sanity check the archive header.  */
4946   if (bfd_read ((PTR) &ar_header, 1, sizeof (struct ar_hdr), abfd)
4947       != sizeof (struct ar_hdr))
4948     return false;
4949
4950   if (strncmp (ar_header.ar_fmag, ARFMAG, 2))
4951     {
4952       bfd_set_error (bfd_error_malformed_archive);
4953       return false;
4954     }
4955
4956   /* How big is the archive symbol table entry?  */
4957   errno = 0;
4958   parsed_size = strtol (ar_header.ar_size, NULL, 10);
4959   if (errno != 0)
4960     {
4961       bfd_set_error (bfd_error_malformed_archive);
4962       return false;
4963     }
4964
4965   /* Save off the file offset of the first real user data.  */
4966   ardata->first_file_filepos = bfd_tell (abfd) + parsed_size;
4967
4968   /* Read in the library symbol table.  We'll make heavy use of this
4969      in just a minute.  */
4970   if (bfd_read ((PTR) & lst_header, 1, sizeof (struct lst_header), abfd)
4971       != sizeof (struct lst_header))
4972     return false;
4973
4974   /* Sanity check.  */
4975   if (lst_header.a_magic != LIBMAGIC)
4976     {
4977       bfd_set_error (bfd_error_malformed_archive);
4978       return false;
4979     }
4980
4981   /* Count the number of symbols in the library symbol table.  */
4982   if (som_bfd_count_ar_symbols (abfd, &lst_header, &ardata->symdef_count)
4983       == false)
4984     return false;
4985
4986   /* Get back to the start of the library symbol table.  */
4987   if (bfd_seek (abfd, ardata->first_file_filepos - parsed_size 
4988                         + sizeof (struct lst_header), SEEK_SET) < 0)
4989     return false;
4990
4991   /* Initializae the cache and allocate space for the library symbols.  */
4992   ardata->cache = 0;
4993   ardata->symdefs = (carsym *) bfd_alloc (abfd,
4994                                           (ardata->symdef_count
4995                                            * sizeof (carsym)));
4996   if (!ardata->symdefs)
4997     {
4998       bfd_set_error (bfd_error_no_memory);
4999       return false;
5000     }
5001
5002   /* Now fill in the canonical archive symbols.  */
5003   if (som_bfd_fill_in_ar_symbols (abfd, &lst_header, &ardata->symdefs)
5004       == false)
5005     return false;
5006
5007   /* Seek back to the "first" file in the archive.  Note the "first"
5008      file may be the extended name table.  */
5009   if (bfd_seek (abfd, ardata->first_file_filepos, SEEK_SET) < 0)
5010     return false;
5011
5012   /* Notify the generic archive code that we have a symbol map.  */
5013   bfd_has_map (abfd) = true;
5014   return true;
5015 }
5016
5017 /* Begin preparing to write a SOM library symbol table.
5018
5019    As part of the prep work we need to determine the number of symbols
5020    and the size of the associated string section.  */
5021
5022 static boolean
5023 som_bfd_prep_for_ar_write (abfd, num_syms, stringsize)
5024      bfd *abfd;
5025      unsigned int *num_syms, *stringsize;
5026 {
5027   bfd *curr_bfd = abfd->archive_head;
5028
5029   /* Some initialization.  */
5030   *num_syms = 0;
5031   *stringsize = 0;
5032
5033   /* Iterate over each BFD within this archive.  */
5034   while (curr_bfd != NULL)
5035     {
5036       unsigned int curr_count, i;
5037       som_symbol_type *sym;
5038
5039       /* Don't bother for non-SOM objects.  */
5040       if (curr_bfd->format != bfd_object
5041           || curr_bfd->xvec->flavour != bfd_target_som_flavour)
5042         {
5043           curr_bfd = curr_bfd->next;
5044           continue;
5045         }
5046
5047       /* Make sure the symbol table has been read, then snag a pointer
5048          to it.  It's a little slimey to grab the symbols via obj_som_symtab,
5049          but doing so avoids allocating lots of extra memory.  */
5050       if (som_slurp_symbol_table (curr_bfd) == false)
5051         return false;
5052
5053       sym = obj_som_symtab (curr_bfd);
5054       curr_count = bfd_get_symcount (curr_bfd);
5055
5056       /* Examine each symbol to determine if it belongs in the
5057          library symbol table.  */
5058       for (i = 0; i < curr_count; i++, sym++)
5059         {
5060           struct som_misc_symbol_info info;
5061
5062           /* Derive SOM information from the BFD symbol.  */
5063           som_bfd_derive_misc_symbol_info (curr_bfd, &sym->symbol, &info);
5064
5065           /* Should we include this symbol?  */
5066           if (info.symbol_type == ST_NULL
5067               || info.symbol_type == ST_SYM_EXT
5068               || info.symbol_type == ST_ARG_EXT)
5069             continue;
5070
5071           /* Only global symbols and unsatisfied commons.  */
5072           if (info.symbol_scope != SS_UNIVERSAL
5073               && info.symbol_type != ST_STORAGE)
5074             continue;
5075
5076           /* Do no include undefined symbols.  */
5077           if (bfd_is_und_section (sym->symbol.section))
5078             continue;
5079
5080           /* Bump the various counters, being careful to honor
5081              alignment considerations in the string table.  */
5082           (*num_syms)++;
5083           *stringsize = *stringsize + strlen (sym->symbol.name) + 5;
5084           while (*stringsize % 4)
5085             (*stringsize)++;
5086         }
5087
5088       curr_bfd = curr_bfd->next;
5089     }
5090   return true;
5091 }
5092
5093 /* Hash a symbol name based on the hashing algorithm presented in the
5094    SOM ABI.  */
5095 static unsigned int
5096 som_bfd_ar_symbol_hash (symbol)
5097      asymbol *symbol;
5098 {
5099   unsigned int len = strlen (symbol->name);
5100
5101   /* Names with length 1 are special.  */
5102   if (len == 1)
5103     return 0x1000100 | (symbol->name[0] << 16) | symbol->name[0];
5104
5105   return ((len & 0x7f) << 24) | (symbol->name[1] << 16)
5106           | (symbol->name[len-2] << 8) | symbol->name[len-1];
5107 }
5108
5109 static CONST char *
5110 normalize (file)
5111      CONST char *file;
5112 {
5113   CONST char *filename = strrchr (file, '/');
5114
5115   if (filename != NULL)
5116     filename++;
5117   else
5118     filename = file;
5119   return filename;
5120 }
5121
5122 /* Do the bulk of the work required to write the SOM library
5123    symbol table.  */
5124    
5125 static boolean
5126 som_bfd_ar_write_symbol_stuff (abfd, nsyms, string_size, lst)
5127      bfd *abfd;
5128      unsigned int nsyms, string_size;
5129      struct lst_header lst;
5130 {
5131   file_ptr lst_filepos;
5132   char *strings = NULL, *p;
5133   struct lst_symbol_record *lst_syms = NULL, *curr_lst_sym;
5134   bfd *curr_bfd;
5135   unsigned int *hash_table = NULL;
5136   struct som_entry *som_dict = NULL;
5137   struct lst_symbol_record **last_hash_entry = NULL;
5138   unsigned int curr_som_offset, som_index, extended_name_length = 0;
5139   unsigned int maxname = abfd->xvec->ar_max_namelen;
5140
5141   hash_table =
5142     (unsigned int *) malloc (lst.hash_size * sizeof (unsigned int));
5143   if (hash_table == NULL && lst.hash_size != 0)
5144     {
5145       bfd_set_error (bfd_error_no_memory);
5146       goto error_return;
5147     }
5148   som_dict =
5149     (struct som_entry *) malloc (lst.module_count
5150                                  * sizeof (struct som_entry));
5151   if (som_dict == NULL && lst.module_count != 0)
5152     {
5153       bfd_set_error (bfd_error_no_memory);
5154       goto error_return;
5155     }
5156
5157   last_hash_entry =
5158     ((struct lst_symbol_record **)
5159      malloc (lst.hash_size * sizeof (struct lst_symbol_record *)));
5160   if (last_hash_entry == NULL && lst.hash_size != 0)
5161     {
5162       bfd_set_error (bfd_error_no_memory);
5163       goto error_return;
5164     }
5165
5166   /* Lots of fields are file positions relative to the start
5167      of the lst record.  So save its location.  */
5168   lst_filepos = bfd_tell (abfd) - sizeof (struct lst_header);
5169
5170   /* Some initialization.  */
5171   memset (hash_table, 0, 4 * lst.hash_size);
5172   memset (som_dict, 0, lst.module_count * sizeof (struct som_entry));
5173   memset (last_hash_entry, 0,   
5174           lst.hash_size * sizeof (struct lst_symbol_record *));
5175
5176   /* Symbols have som_index fields, so we have to keep track of the
5177      index of each SOM in the archive.
5178
5179      The SOM dictionary has (among other things) the absolute file
5180      position for the SOM which a particular dictionary entry
5181      describes.  We have to compute that information as we iterate
5182      through the SOMs/symbols.  */
5183   som_index = 0;
5184   curr_som_offset = 8 + 2 * sizeof (struct ar_hdr) + lst.file_end;
5185
5186   /* Yow!  We have to know the size of the extended name table
5187      too.  */
5188   for (curr_bfd = abfd->archive_head;
5189        curr_bfd != NULL;
5190        curr_bfd = curr_bfd->next)
5191     {
5192       CONST char *normal = normalize (curr_bfd->filename);
5193       unsigned int thislen;
5194
5195       if (!normal)
5196         {
5197           bfd_set_error (bfd_error_no_memory);
5198           return false;
5199         }
5200       thislen = strlen (normal);
5201       if (thislen > maxname)
5202         extended_name_length += thislen + 1;
5203     }
5204
5205   /* Make room for the archive header and the contents of the
5206      extended string table.  */
5207   if (extended_name_length)
5208     curr_som_offset += extended_name_length + sizeof (struct ar_hdr);
5209
5210   /* Make sure we're properly aligned.  */
5211   curr_som_offset = (curr_som_offset + 0x1) & ~0x1;
5212
5213   /* FIXME should be done with buffers just like everything else... */
5214   lst_syms = malloc (nsyms * sizeof (struct lst_symbol_record));
5215   if (lst_syms == NULL && nsyms != 0)
5216     {
5217       bfd_set_error (bfd_error_no_memory);
5218       goto error_return;
5219     }
5220   strings = malloc (string_size);
5221   if (strings == NULL && string_size != 0)
5222     {
5223       bfd_set_error (bfd_error_no_memory);
5224       goto error_return;
5225     }
5226
5227   p = strings;
5228   curr_lst_sym = lst_syms;
5229
5230   curr_bfd = abfd->archive_head;
5231   while (curr_bfd != NULL)
5232     {
5233       unsigned int curr_count, i;
5234       som_symbol_type *sym;
5235
5236       /* Don't bother for non-SOM objects.  */
5237       if (curr_bfd->format != bfd_object
5238           || curr_bfd->xvec->flavour != bfd_target_som_flavour)
5239         {
5240           curr_bfd = curr_bfd->next;
5241           continue;
5242         }
5243
5244       /* Make sure the symbol table has been read, then snag a pointer
5245          to it.  It's a little slimey to grab the symbols via obj_som_symtab,
5246          but doing so avoids allocating lots of extra memory.  */
5247       if (som_slurp_symbol_table (curr_bfd) == false)
5248         goto error_return;
5249
5250       sym = obj_som_symtab (curr_bfd);
5251       curr_count = bfd_get_symcount (curr_bfd);
5252
5253       for (i = 0; i < curr_count; i++, sym++)
5254         {
5255           struct som_misc_symbol_info info;
5256
5257           /* Derive SOM information from the BFD symbol.  */
5258           som_bfd_derive_misc_symbol_info (curr_bfd, &sym->symbol, &info);
5259
5260           /* Should we include this symbol?  */
5261           if (info.symbol_type == ST_NULL
5262               || info.symbol_type == ST_SYM_EXT
5263               || info.symbol_type == ST_ARG_EXT)
5264             continue;
5265
5266           /* Only global symbols and unsatisfied commons.  */
5267           if (info.symbol_scope != SS_UNIVERSAL
5268               && info.symbol_type != ST_STORAGE)
5269             continue;
5270
5271           /* Do no include undefined symbols.  */
5272           if (bfd_is_und_section (sym->symbol.section))
5273             continue;
5274
5275           /* If this is the first symbol from this SOM, then update
5276              the SOM dictionary too.  */
5277           if (som_dict[som_index].location == 0)
5278             {
5279               som_dict[som_index].location = curr_som_offset;
5280               som_dict[som_index].length = arelt_size (curr_bfd);
5281             }
5282
5283           /* Fill in the lst symbol record.  */
5284           curr_lst_sym->hidden = 0;
5285           curr_lst_sym->secondary_def = 0;
5286           curr_lst_sym->symbol_type = info.symbol_type;
5287           curr_lst_sym->symbol_scope = info.symbol_scope;
5288           curr_lst_sym->check_level = 0;
5289           curr_lst_sym->must_qualify = 0;
5290           curr_lst_sym->initially_frozen = 0;
5291           curr_lst_sym->memory_resident = 0;
5292           curr_lst_sym->is_common = bfd_is_com_section (sym->symbol.section);
5293           curr_lst_sym->dup_common = 0;
5294           curr_lst_sym->xleast = 0;
5295           curr_lst_sym->arg_reloc = info.arg_reloc;
5296           curr_lst_sym->name.n_strx = p - strings + 4;
5297           curr_lst_sym->qualifier_name.n_strx = 0;
5298           curr_lst_sym->symbol_info = info.symbol_info;
5299           curr_lst_sym->symbol_value = info.symbol_value;
5300           curr_lst_sym->symbol_descriptor = 0;
5301           curr_lst_sym->reserved = 0;
5302           curr_lst_sym->som_index = som_index;
5303           curr_lst_sym->symbol_key = som_bfd_ar_symbol_hash (&sym->symbol);
5304           curr_lst_sym->next_entry = 0;
5305
5306           /* Insert into the hash table.  */
5307           if (hash_table[curr_lst_sym->symbol_key % lst.hash_size])
5308             {
5309               struct lst_symbol_record *tmp;
5310
5311               /* There is already something at the head of this hash chain,
5312                  so tack this symbol onto the end of the chain.  */
5313               tmp = last_hash_entry[curr_lst_sym->symbol_key % lst.hash_size];
5314               tmp->next_entry
5315                 = (curr_lst_sym - lst_syms) * sizeof (struct lst_symbol_record)
5316                   + lst.hash_size * 4 
5317                   + lst.module_count * sizeof (struct som_entry)
5318                   + sizeof (struct lst_header);
5319             }
5320           else
5321             {
5322               /* First entry in this hash chain.  */
5323               hash_table[curr_lst_sym->symbol_key % lst.hash_size]
5324                 = (curr_lst_sym - lst_syms) * sizeof (struct lst_symbol_record)
5325                   + lst.hash_size * 4 
5326                   + lst.module_count * sizeof (struct som_entry)
5327                   + sizeof (struct lst_header);
5328             }
5329
5330           /* Keep track of the last symbol we added to this chain so we can
5331              easily update its next_entry pointer.  */
5332           last_hash_entry[curr_lst_sym->symbol_key % lst.hash_size]
5333             = curr_lst_sym;
5334
5335
5336           /* Update the string table.  */
5337           bfd_put_32 (abfd, strlen (sym->symbol.name), p);
5338           p += 4;
5339           strcpy (p, sym->symbol.name);
5340           p += strlen (sym->symbol.name) + 1;
5341           while ((int)p % 4)
5342             {
5343               bfd_put_8 (abfd, 0, p);
5344               p++;
5345             }
5346
5347           /* Head to the next symbol.  */
5348           curr_lst_sym++;
5349         }
5350
5351       /* Keep track of where each SOM will finally reside; then look
5352          at the next BFD.  */
5353       curr_som_offset += arelt_size (curr_bfd) + sizeof (struct ar_hdr);
5354       curr_bfd = curr_bfd->next;
5355       som_index++;
5356     }
5357
5358   /* Now scribble out the hash table.  */
5359   if (bfd_write ((PTR) hash_table, lst.hash_size, 4, abfd)
5360       != lst.hash_size * 4)
5361     goto error_return;
5362
5363   /* Then the SOM dictionary.  */
5364   if (bfd_write ((PTR) som_dict, lst.module_count,
5365                  sizeof (struct som_entry), abfd)
5366       != lst.module_count * sizeof (struct som_entry))
5367     goto error_return;
5368
5369   /* The library symbols.  */
5370   if (bfd_write ((PTR) lst_syms, nsyms, sizeof (struct lst_symbol_record), abfd)
5371       != nsyms * sizeof (struct lst_symbol_record))
5372     goto error_return;
5373
5374   /* And finally the strings.  */
5375   if (bfd_write ((PTR) strings, string_size, 1, abfd) != string_size)
5376     goto error_return;
5377
5378   if (hash_table != NULL)
5379     free (hash_table);
5380   if (som_dict != NULL)
5381     free (som_dict);
5382   if (last_hash_entry != NULL)
5383     free (last_hash_entry);
5384   if (lst_syms != NULL)
5385     free (lst_syms);
5386   if (strings != NULL)
5387     free (strings);
5388   return true;
5389
5390  error_return:
5391   if (hash_table != NULL)
5392     free (hash_table);
5393   if (som_dict != NULL)
5394     free (som_dict);
5395   if (last_hash_entry != NULL)
5396     free (last_hash_entry);
5397   if (lst_syms != NULL)
5398     free (lst_syms);
5399   if (strings != NULL)
5400     free (strings);
5401
5402   return false;
5403 }
5404
5405 /* Write out the LST for the archive.
5406
5407    You'll never believe this is really how armaps are handled in SOM...  */
5408
5409 /*ARGSUSED*/
5410 static boolean
5411 som_write_armap (abfd, elength, map, orl_count, stridx)
5412      bfd *abfd;
5413      unsigned int elength;
5414      struct orl *map;
5415      unsigned int orl_count;
5416      int stridx;
5417 {
5418   bfd *curr_bfd;
5419   struct stat statbuf;
5420   unsigned int i, lst_size, nsyms, stringsize;
5421   struct ar_hdr hdr;
5422   struct lst_header lst;
5423   int *p;
5424  
5425   /* We'll use this for the archive's date and mode later.  */
5426   if (stat (abfd->filename, &statbuf) != 0)
5427     {
5428       bfd_set_error (bfd_error_system_call);
5429       return false;
5430     }
5431   /* Fudge factor.  */
5432   bfd_ardata (abfd)->armap_timestamp = statbuf.st_mtime + 60;
5433
5434   /* Account for the lst header first.  */
5435   lst_size = sizeof (struct lst_header);
5436
5437   /* Start building the LST header.  */
5438   lst.system_id = CPU_PA_RISC1_0;
5439   lst.a_magic = LIBMAGIC;
5440   lst.version_id = VERSION_ID;
5441   lst.file_time.secs = 0;
5442   lst.file_time.nanosecs = 0;
5443
5444   lst.hash_loc = lst_size;
5445   lst.hash_size = SOM_LST_HASH_SIZE;
5446
5447   /* Hash table is a SOM_LST_HASH_SIZE 32bit offsets.  */
5448   lst_size += 4 * SOM_LST_HASH_SIZE;
5449
5450   /* We need to count the number of SOMs in this archive.  */
5451   curr_bfd = abfd->archive_head;
5452   lst.module_count = 0;
5453   while (curr_bfd != NULL)
5454     {
5455       /* Only true SOM objects count.  */
5456       if (curr_bfd->format == bfd_object
5457           && curr_bfd->xvec->flavour == bfd_target_som_flavour)
5458         lst.module_count++;
5459       curr_bfd = curr_bfd->next;
5460     }
5461   lst.module_limit = lst.module_count;
5462   lst.dir_loc = lst_size;
5463   lst_size += sizeof (struct som_entry) * lst.module_count;
5464
5465   /* We don't support import/export tables, auxiliary headers,
5466      or free lists yet.  Make the linker work a little harder
5467      to make our life easier.  */
5468
5469   lst.export_loc = 0;
5470   lst.export_count = 0;
5471   lst.import_loc = 0;
5472   lst.aux_loc = 0;
5473   lst.aux_size = 0;
5474
5475   /* Count how many symbols we will have on the hash chains and the
5476      size of the associated string table.  */
5477   if (som_bfd_prep_for_ar_write (abfd, &nsyms, &stringsize) == false)
5478     return false;
5479
5480   lst_size += sizeof (struct lst_symbol_record) * nsyms;
5481
5482   /* For the string table.  One day we might actually use this info
5483      to avoid small seeks/reads when reading archives.  */
5484   lst.string_loc = lst_size;
5485   lst.string_size = stringsize;
5486   lst_size += stringsize;
5487
5488   /* SOM ABI says this must be zero.  */
5489   lst.free_list = 0;
5490   lst.file_end = lst_size;
5491
5492   /* Compute the checksum.  Must happen after the entire lst header
5493      has filled in.  */
5494   p = (int *)&lst;
5495   lst.checksum = 0;
5496   for (i = 0; i < sizeof (struct lst_header)/sizeof (int) - 1; i++)
5497     lst.checksum ^= *p++;
5498
5499   sprintf (hdr.ar_name, "/               ");
5500   sprintf (hdr.ar_date, "%ld", bfd_ardata (abfd)->armap_timestamp);
5501   sprintf (hdr.ar_uid, "%ld", (long) getuid ());
5502   sprintf (hdr.ar_gid, "%ld", (long) getgid ());
5503   sprintf (hdr.ar_mode, "%-8o", (unsigned int) statbuf.st_mode);
5504   sprintf (hdr.ar_size, "%-10d", (int) lst_size);
5505   hdr.ar_fmag[0] = '`';
5506   hdr.ar_fmag[1] = '\012';
5507
5508   /* Turn any nulls into spaces.  */
5509   for (i = 0; i < sizeof (struct ar_hdr); i++)
5510     if (((char *) (&hdr))[i] == '\0')
5511       (((char *) (&hdr))[i]) = ' ';
5512
5513   /* Scribble out the ar header.  */
5514   if (bfd_write ((PTR) &hdr, 1, sizeof (struct ar_hdr), abfd)
5515       != sizeof (struct ar_hdr))
5516     return false;
5517
5518   /* Now scribble out the lst header.  */
5519   if (bfd_write ((PTR) &lst, 1, sizeof (struct lst_header), abfd)
5520       != sizeof (struct lst_header))
5521     return false;
5522
5523   /* Build and write the armap.  */
5524   if (som_bfd_ar_write_symbol_stuff (abfd, nsyms, stringsize, lst) == false)
5525     return false;
5526   
5527   /* Done.  */
5528   return true;
5529 }
5530
5531 /* Free all information we have cached for this BFD.  We can always
5532    read it again later if we need it.  */
5533
5534 static boolean
5535 som_bfd_free_cached_info (abfd)
5536      bfd *abfd;
5537 {
5538   asection *o;
5539
5540   if (bfd_get_format (abfd) != bfd_object)
5541     return true;
5542
5543 #define FREE(x) if (x != NULL) { free (x); x = NULL; }
5544   /* Free the native string and symbol tables.  */
5545   FREE (obj_som_symtab (abfd));
5546   FREE (obj_som_stringtab (abfd));
5547   for (o = abfd->sections; o != (asection *) NULL; o = o->next)
5548     {
5549       /* Free the native relocations.  */
5550       o->reloc_count = -1;
5551       FREE (som_section_data (o)->reloc_stream);
5552       /* Free the generic relocations.  */
5553       FREE (o->relocation);
5554     }
5555 #undef FREE
5556
5557   return true;
5558 }
5559
5560 /* End of miscellaneous support functions. */
5561
5562 #define som_close_and_cleanup           som_bfd_free_cached_info
5563
5564 #define som_openr_next_archived_file    bfd_generic_openr_next_archived_file
5565 #define som_generic_stat_arch_elt       bfd_generic_stat_arch_elt
5566 #define som_truncate_arname             bfd_bsd_truncate_arname
5567 #define som_slurp_extended_name_table   _bfd_slurp_extended_name_table
5568 #define som_update_armap_timestamp      bfd_true
5569
5570 #define som_get_lineno                  _bfd_nosymbols_get_lineno
5571 #define som_bfd_make_debug_symbol       _bfd_nosymbols_bfd_make_debug_symbol
5572
5573 #define som_bfd_get_relocated_section_contents \
5574  bfd_generic_get_relocated_section_contents
5575 #define som_bfd_relax_section bfd_generic_relax_section
5576 #define som_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
5577 #define som_bfd_link_add_symbols _bfd_generic_link_add_symbols
5578 #define som_bfd_final_link _bfd_generic_final_link
5579
5580 const bfd_target som_vec =
5581 {
5582   "som",                        /* name */
5583   bfd_target_som_flavour,
5584   true,                         /* target byte order */
5585   true,                         /* target headers byte order */
5586   (HAS_RELOC | EXEC_P |         /* object flags */
5587    HAS_LINENO | HAS_DEBUG |
5588    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED | DYNAMIC),
5589   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
5590    | SEC_ALLOC | SEC_LOAD | SEC_RELOC),         /* section flags */
5591
5592 /* leading_symbol_char: is the first char of a user symbol
5593    predictable, and if so what is it */
5594   0,
5595   '/',                          /* ar_pad_char */
5596   14,                           /* ar_max_namelen */
5597   3,                            /* minimum alignment */
5598   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
5599   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
5600   bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* data */
5601   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
5602   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
5603   bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* hdrs */
5604   {_bfd_dummy_target,
5605    som_object_p,                /* bfd_check_format */
5606    bfd_generic_archive_p,
5607    _bfd_dummy_target
5608   },
5609   {
5610     bfd_false,
5611     som_mkobject,
5612     _bfd_generic_mkarchive,
5613     bfd_false
5614   },
5615   {
5616     bfd_false,
5617     som_write_object_contents,
5618     _bfd_write_archive_contents,
5619     bfd_false,
5620   },
5621 #undef som
5622
5623   BFD_JUMP_TABLE_GENERIC (som),
5624   BFD_JUMP_TABLE_COPY (som),
5625   BFD_JUMP_TABLE_CORE (_bfd_nocore),
5626   BFD_JUMP_TABLE_ARCHIVE (som),
5627   BFD_JUMP_TABLE_SYMBOLS (som),
5628   BFD_JUMP_TABLE_RELOCS (som),
5629   BFD_JUMP_TABLE_WRITE (som),
5630   BFD_JUMP_TABLE_LINK (som),
5631   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
5632
5633   (PTR) 0
5634 };
5635
5636 #endif /* HOST_HPPAHPUX || HOST_HPPABSD || HOST_HPPAOSF */