* som.c (som_write_fixups, case R_ENTRY): Handle case where no
[platform/upstream/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                && bfd_is_und_section (sym->section)
3427                && sym->flags & BSF_FUNCTION)
3428         info->symbol_type = ST_CODE;
3429
3430       /* Handle function symbols which were defined in this file.
3431          They should have type ST_ENTRY.  Also retrieve the argument
3432          relocation bits from the SOM backend information.  */
3433       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_ENTRY
3434                || (som_symbol_data (sym)->som_type == SYMBOL_TYPE_CODE
3435                    && (sym->flags & BSF_FUNCTION))
3436                || (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN
3437                    && (sym->flags & BSF_FUNCTION)))
3438         {
3439           info->symbol_type = ST_ENTRY;
3440           info->arg_reloc = som_symbol_data (sym)->tc_data.hppa_arg_reloc;
3441         }
3442
3443       /* If the type is unknown at this point, it should be
3444          ST_DATA (functions were handled as special cases above).  */
3445       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN)
3446         info->symbol_type = ST_DATA;
3447
3448       /* From now on it's a very simple mapping.  */
3449       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_ABSOLUTE)
3450         info->symbol_type = ST_ABSOLUTE;
3451       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_CODE)
3452         info->symbol_type = ST_CODE;
3453       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_DATA)
3454         info->symbol_type = ST_DATA;
3455       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_MILLICODE)
3456         info->symbol_type = ST_MILLICODE;
3457       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_PLABEL)
3458         info->symbol_type = ST_PLABEL;
3459       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_PRI_PROG)
3460         info->symbol_type = ST_PRI_PROG;
3461       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_SEC_PROG)
3462         info->symbol_type = ST_SEC_PROG;
3463     }
3464         
3465   /* Now handle the symbol's scope.  Exported data which is not
3466      in the common section has scope SS_UNIVERSAL.  Note scope
3467      of common symbols was handled earlier!  */
3468   if (sym->flags & BSF_EXPORT && ! bfd_is_com_section (sym->section))
3469     info->symbol_scope = SS_UNIVERSAL;
3470   /* Any undefined symbol at this point has a scope SS_UNSAT.  */
3471   else if (bfd_is_und_section (sym->section))
3472     info->symbol_scope = SS_UNSAT;
3473   /* Anything else which is not in the common section has scope
3474      SS_LOCAL.  */
3475   else if (! bfd_is_com_section (sym->section))
3476     info->symbol_scope = SS_LOCAL;
3477
3478   /* Now set the symbol_info field.  It has no real meaning
3479      for undefined or common symbols, but the HP linker will
3480      choke if it's not set to some "reasonable" value.  We
3481      use zero as a reasonable value.  */
3482   if (bfd_is_com_section (sym->section)
3483       || bfd_is_und_section (sym->section)
3484       || bfd_is_abs_section (sym->section))
3485     info->symbol_info = 0;
3486   /* For all other symbols, the symbol_info field contains the 
3487      subspace index of the space this symbol is contained in.  */
3488   else
3489     info->symbol_info = sym->section->target_index;
3490
3491   /* Set the symbol's value.  */
3492   info->symbol_value = sym->value + sym->section->vma;
3493 }
3494
3495 /* Build and write, in one big chunk, the entire symbol table for
3496    this BFD.  */
3497
3498 static boolean
3499 som_build_and_write_symbol_table (abfd)
3500      bfd *abfd;
3501 {
3502   unsigned int num_syms = bfd_get_symcount (abfd);
3503   file_ptr symtab_location = obj_som_file_hdr (abfd)->symbol_location;
3504   asymbol **bfd_syms = bfd_get_outsymbols (abfd);
3505   struct symbol_dictionary_record *som_symtab = NULL;
3506   int i, symtab_size;
3507
3508   /* Compute total symbol table size and allocate a chunk of memory
3509      to hold the symbol table as we build it.  */
3510   symtab_size = num_syms * sizeof (struct symbol_dictionary_record);
3511   som_symtab = (struct symbol_dictionary_record *) malloc (symtab_size);
3512   if (som_symtab == NULL && symtab_size != 0)
3513     {
3514       bfd_set_error (bfd_error_no_memory);
3515       goto error_return;
3516     }
3517   memset (som_symtab, 0, symtab_size);
3518
3519   /* Walk over each symbol.  */
3520   for (i = 0; i < num_syms; i++)
3521     {
3522       struct som_misc_symbol_info info;
3523
3524       /* This is really an index into the symbol strings table.  
3525          By the time we get here, the index has already been 
3526          computed and stored into the name field in the BFD symbol.  */
3527       som_symtab[i].name.n_strx = (int) bfd_syms[i]->name;
3528
3529       /* Derive SOM information from the BFD symbol.  */
3530       som_bfd_derive_misc_symbol_info (abfd, bfd_syms[i], &info);
3531
3532       /* Now use it.  */
3533       som_symtab[i].symbol_type = info.symbol_type;
3534       som_symtab[i].symbol_scope = info.symbol_scope;
3535       som_symtab[i].arg_reloc = info.arg_reloc;
3536       som_symtab[i].symbol_info = info.symbol_info;
3537       som_symtab[i].symbol_value = info.symbol_value;
3538     }
3539
3540   /* Everything is ready, seek to the right location and
3541      scribble out the symbol table.  */
3542   if (bfd_seek (abfd, symtab_location, SEEK_SET) != 0)
3543     return false;
3544
3545   if (bfd_write ((PTR) som_symtab, symtab_size, 1, abfd) != symtab_size)
3546     goto error_return;
3547
3548   if (som_symtab != NULL)
3549     free (som_symtab);
3550   return true;
3551  error_return:
3552   if (som_symtab != NULL)
3553     free (som_symtab);
3554   return false;
3555 }
3556
3557 /* Write an object in SOM format.  */  
3558
3559 static boolean
3560 som_write_object_contents (abfd)
3561      bfd *abfd;
3562 {
3563   if (abfd->output_has_begun == false)
3564     {
3565       /* Set up fixed parts of the file, space, and subspace headers.
3566          Notify the world that output has begun.  */
3567       som_prep_headers (abfd);
3568       abfd->output_has_begun = true;
3569       /* Start writing the object file.  This include all the string
3570          tables, fixup streams, and other portions of the object file.  */
3571       som_begin_writing (abfd);
3572     }
3573
3574   /* Now that the symbol table information is complete, build and
3575      write the symbol table.  */
3576   if (som_build_and_write_symbol_table (abfd) == false)
3577     return false;
3578
3579   return (som_write_headers (abfd));
3580 }
3581
3582 \f
3583 /* Read and save the string table associated with the given BFD.  */
3584
3585 static boolean
3586 som_slurp_string_table (abfd)
3587      bfd *abfd;
3588 {
3589   char *stringtab;
3590
3591   /* Use the saved version if its available.  */
3592   if (obj_som_stringtab (abfd) != NULL)
3593     return true;
3594
3595   /* I don't think this can currently happen, and I'm not sure it should
3596      really be an error, but it's better than getting unpredictable results
3597      from the host's malloc when passed a size of zero.  */
3598   if (obj_som_stringtab_size (abfd) == 0)
3599     {
3600       bfd_set_error (bfd_error_no_symbols);
3601       return false;
3602     }
3603
3604   /* Allocate and read in the string table.  */
3605   stringtab = malloc (obj_som_stringtab_size (abfd));
3606   if (stringtab == NULL)
3607     {
3608       bfd_set_error (bfd_error_no_memory);
3609       return false;
3610     }
3611
3612   if (bfd_seek (abfd, obj_som_str_filepos (abfd), SEEK_SET) < 0)
3613     return false;
3614   
3615   if (bfd_read (stringtab, obj_som_stringtab_size (abfd), 1, abfd)
3616       != obj_som_stringtab_size (abfd))
3617     return false;
3618
3619   /* Save our results and return success. */
3620   obj_som_stringtab (abfd) = stringtab;
3621   return true;
3622 }
3623
3624 /* Return the amount of data (in bytes) required to hold the symbol
3625    table for this object.  */
3626
3627 static long
3628 som_get_symtab_upper_bound (abfd)
3629      bfd *abfd;
3630 {
3631   if (!som_slurp_symbol_table (abfd))
3632     return -1;
3633
3634   return (bfd_get_symcount (abfd) + 1) * (sizeof (asymbol *));
3635 }
3636
3637 /* Convert from a SOM subspace index to a BFD section.  */
3638
3639 static asection *
3640 bfd_section_from_som_symbol (abfd, symbol)
3641      bfd *abfd;
3642      struct symbol_dictionary_record *symbol;
3643 {
3644   asection *section;
3645
3646   /* The meaning of the symbol_info field changes for functions
3647      within executables.  So only use the quick symbol_info mapping for
3648      incomplete objects and non-function symbols in executables.  */
3649   if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0
3650       || (symbol->symbol_type != ST_ENTRY
3651           && symbol->symbol_type != ST_PRI_PROG
3652           && symbol->symbol_type != ST_SEC_PROG
3653           && symbol->symbol_type != ST_MILLICODE))
3654     {
3655       unsigned int index = symbol->symbol_info;
3656       for (section = abfd->sections; section != NULL; section = section->next)
3657         if (section->target_index == index)
3658           return section;
3659
3660       /* Should never happen.  */
3661       abort();
3662     }
3663   else
3664     {
3665       unsigned int value = symbol->symbol_value;
3666
3667       /* For executables we will have to use the symbol's address and
3668          find out what section would contain that address.   Yuk.  */
3669       for (section = abfd->sections; section; section = section->next)
3670         {
3671           if (value >= section->vma
3672               && value <= section->vma + section->_cooked_size)
3673             return section;
3674         }
3675
3676       /* Should never happen.  */
3677       abort ();
3678     }
3679 }
3680
3681 /* Read and save the symbol table associated with the given BFD.  */
3682
3683 static unsigned int
3684 som_slurp_symbol_table (abfd)
3685      bfd *abfd;
3686 {
3687   int symbol_count = bfd_get_symcount (abfd);
3688   int symsize = sizeof (struct symbol_dictionary_record);
3689   char *stringtab;
3690   struct symbol_dictionary_record *buf = NULL, *bufp, *endbufp;
3691   som_symbol_type *sym, *symbase;
3692
3693   /* Return saved value if it exists.  */
3694   if (obj_som_symtab (abfd) != NULL)
3695     goto successful_return;
3696
3697   /* Special case.  This is *not* an error.  */
3698   if (symbol_count == 0)
3699     goto successful_return;
3700
3701   if (!som_slurp_string_table (abfd))
3702     goto error_return;
3703
3704   stringtab = obj_som_stringtab (abfd);
3705
3706   symbase = (som_symbol_type *)
3707     malloc (symbol_count * sizeof (som_symbol_type));
3708   if (symbase == NULL)
3709     {
3710       bfd_set_error (bfd_error_no_memory);
3711       goto error_return;
3712     }
3713
3714   /* Read in the external SOM representation.  */
3715   buf = malloc (symbol_count * symsize);
3716   if (buf == NULL && symbol_count * symsize != 0)
3717     {
3718       bfd_set_error (bfd_error_no_memory);
3719       goto error_return;
3720     }
3721   if (bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET) < 0)
3722     goto error_return;
3723   if (bfd_read (buf, symbol_count * symsize, 1, abfd) 
3724       != symbol_count * symsize)
3725     goto error_return;
3726
3727   /* Iterate over all the symbols and internalize them.  */
3728   endbufp = buf + symbol_count;
3729   for (bufp = buf, sym = symbase; bufp < endbufp; ++bufp)
3730     {
3731
3732       /* I don't think we care about these.  */
3733       if (bufp->symbol_type == ST_SYM_EXT
3734           || bufp->symbol_type == ST_ARG_EXT)
3735         continue;
3736
3737       /* Set some private data we care about.  */
3738       if (bufp->symbol_type == ST_NULL)
3739         som_symbol_data (sym)->som_type = SYMBOL_TYPE_UNKNOWN;
3740       else if (bufp->symbol_type == ST_ABSOLUTE)
3741         som_symbol_data (sym)->som_type = SYMBOL_TYPE_ABSOLUTE;
3742       else if (bufp->symbol_type == ST_DATA)
3743         som_symbol_data (sym)->som_type = SYMBOL_TYPE_DATA;
3744       else if (bufp->symbol_type == ST_CODE)
3745         som_symbol_data (sym)->som_type = SYMBOL_TYPE_CODE;
3746       else if (bufp->symbol_type == ST_PRI_PROG)
3747         som_symbol_data (sym)->som_type = SYMBOL_TYPE_PRI_PROG;
3748       else if (bufp->symbol_type == ST_SEC_PROG)
3749         som_symbol_data (sym)->som_type = SYMBOL_TYPE_SEC_PROG;
3750       else if (bufp->symbol_type == ST_ENTRY)
3751         som_symbol_data (sym)->som_type = SYMBOL_TYPE_ENTRY;
3752       else if (bufp->symbol_type == ST_MILLICODE)
3753         som_symbol_data (sym)->som_type = SYMBOL_TYPE_MILLICODE;
3754       else if (bufp->symbol_type == ST_PLABEL)
3755         som_symbol_data (sym)->som_type = SYMBOL_TYPE_PLABEL;
3756       else
3757         som_symbol_data (sym)->som_type = SYMBOL_TYPE_UNKNOWN;
3758       som_symbol_data (sym)->tc_data.hppa_arg_reloc = bufp->arg_reloc;
3759
3760       /* Some reasonable defaults.  */
3761       sym->symbol.the_bfd = abfd;
3762       sym->symbol.name = bufp->name.n_strx + stringtab;
3763       sym->symbol.value = bufp->symbol_value;
3764       sym->symbol.section = 0;
3765       sym->symbol.flags = 0;
3766
3767       switch (bufp->symbol_type)
3768         {
3769         case ST_ENTRY:
3770         case ST_PRI_PROG:
3771         case ST_SEC_PROG:
3772         case ST_MILLICODE:
3773           sym->symbol.flags |= BSF_FUNCTION;
3774           sym->symbol.value &= ~0x3;
3775           break;
3776
3777         case ST_STUB:
3778         case ST_CODE:
3779           sym->symbol.value &= ~0x3;
3780
3781         default:
3782           break;
3783         }
3784
3785       /* Handle scoping and section information.  */
3786       switch (bufp->symbol_scope)
3787         {
3788         /* symbol_info field is undefined for SS_EXTERNAL and SS_UNSAT symbols,
3789            so the section associated with this symbol can't be known.  */
3790         case SS_EXTERNAL:
3791           if (bufp->symbol_type != ST_STORAGE)
3792             sym->symbol.section = bfd_und_section_ptr;
3793           else
3794             sym->symbol.section = bfd_com_section_ptr;
3795           sym->symbol.flags |= (BSF_EXPORT | BSF_GLOBAL);
3796           break;
3797
3798         case SS_UNSAT:
3799           if (bufp->symbol_type != ST_STORAGE)
3800             sym->symbol.section = bfd_und_section_ptr;
3801           else
3802             sym->symbol.section = bfd_com_section_ptr;
3803           break;
3804
3805         case SS_UNIVERSAL:
3806           sym->symbol.flags |= (BSF_EXPORT | BSF_GLOBAL);
3807           sym->symbol.section = bfd_section_from_som_symbol (abfd, bufp);
3808           sym->symbol.value -= sym->symbol.section->vma;
3809           break;
3810
3811 #if 0
3812         /* SS_GLOBAL and SS_LOCAL are two names for the same thing.
3813            Sound dumb?  It is.  */
3814         case SS_GLOBAL:
3815 #endif
3816         case SS_LOCAL:
3817           sym->symbol.flags |= BSF_LOCAL;
3818           sym->symbol.section = bfd_section_from_som_symbol (abfd, bufp);
3819           sym->symbol.value -= sym->symbol.section->vma;
3820           break;
3821         }
3822
3823       /* Mark section symbols and symbols used by the debugger.  */
3824       if (sym->symbol.name[0] == '$'
3825           && sym->symbol.name[strlen (sym->symbol.name) - 1] == '$')
3826         sym->symbol.flags |= BSF_SECTION_SYM;
3827       else if (!strncmp (sym->symbol.name, "L$0\002", 4))
3828         {
3829           sym->symbol.flags |= BSF_SECTION_SYM;
3830           sym->symbol.name = sym->symbol.section->name;
3831         }
3832       else if (!strncmp (sym->symbol.name, "L$0\001", 4))
3833         sym->symbol.flags |= BSF_DEBUGGING;
3834
3835       /* Note increment at bottom of loop, since we skip some symbols
3836          we can not include it as part of the for statement.  */
3837       sym++;
3838     }
3839
3840   /* Save our results and return success.  */
3841   obj_som_symtab (abfd) = symbase;
3842  successful_return:
3843   if (buf != NULL)
3844     free (buf);
3845   return (true);
3846
3847  error_return:
3848   if (buf != NULL)
3849     free (buf);
3850   return false;
3851 }
3852
3853 /* Canonicalize a SOM symbol table.  Return the number of entries
3854    in the symbol table.  */
3855
3856 static long
3857 som_get_symtab (abfd, location)
3858      bfd *abfd;
3859      asymbol **location;
3860 {
3861   int i;
3862   som_symbol_type *symbase;
3863
3864   if (!som_slurp_symbol_table (abfd))
3865     return -1;
3866
3867   i = bfd_get_symcount (abfd);
3868   symbase = obj_som_symtab (abfd);
3869
3870   for (; i > 0; i--, location++, symbase++)
3871     *location = &symbase->symbol;
3872
3873   /* Final null pointer.  */
3874   *location = 0;
3875   return (bfd_get_symcount (abfd));
3876 }
3877
3878 /* Make a SOM symbol.  There is nothing special to do here.  */
3879
3880 static asymbol *
3881 som_make_empty_symbol (abfd)
3882      bfd *abfd;
3883 {
3884   som_symbol_type *new =
3885   (som_symbol_type *) bfd_zalloc (abfd, sizeof (som_symbol_type));
3886   if (new == NULL)
3887     {
3888       bfd_set_error (bfd_error_no_memory);
3889       return 0;
3890     }
3891   new->symbol.the_bfd = abfd;
3892
3893   return &new->symbol;
3894 }
3895
3896 /* Print symbol information.  */
3897
3898 static void
3899 som_print_symbol (ignore_abfd, afile, symbol, how)
3900      bfd *ignore_abfd;
3901      PTR afile;
3902      asymbol *symbol;
3903      bfd_print_symbol_type how;
3904 {
3905   FILE *file = (FILE *) afile;
3906   switch (how)
3907     {
3908     case bfd_print_symbol_name:
3909       fprintf (file, "%s", symbol->name);
3910       break;
3911     case bfd_print_symbol_more:
3912       fprintf (file, "som ");
3913       fprintf_vma (file, symbol->value);
3914       fprintf (file, " %lx", (long) symbol->flags);
3915       break;
3916     case bfd_print_symbol_all:
3917       {
3918         CONST char *section_name;
3919         section_name = symbol->section ? symbol->section->name : "(*none*)";
3920         bfd_print_symbol_vandf ((PTR) file, symbol);
3921         fprintf (file, " %s\t%s", section_name, symbol->name);
3922         break;
3923       }
3924     }
3925 }
3926
3927 static boolean
3928 som_bfd_is_local_label (abfd, sym)
3929      bfd *abfd;
3930      asymbol *sym;
3931 {
3932   return (sym->name[0] == 'L' && sym->name[1] == '$');
3933 }
3934
3935 /* Count or process variable-length SOM fixup records.
3936
3937    To avoid code duplication we use this code both to compute the number
3938    of relocations requested by a stream, and to internalize the stream.
3939
3940    When computing the number of relocations requested by a stream the
3941    variables rptr, section, and symbols have no meaning.
3942
3943    Return the number of relocations requested by the fixup stream.  When
3944    not just counting 
3945
3946    This needs at least two or three more passes to get it cleaned up.  */
3947
3948 static unsigned int
3949 som_set_reloc_info (fixup, end, internal_relocs, section, symbols, just_count)
3950      unsigned char *fixup;
3951      unsigned int end;
3952      arelent *internal_relocs;
3953      asection *section;
3954      asymbol **symbols;
3955      boolean just_count;
3956 {
3957   unsigned int op, varname;
3958   unsigned char *end_fixups = &fixup[end];
3959   const struct fixup_format *fp;
3960   char *cp;
3961   unsigned char *save_fixup;
3962   int variables[26], stack[20], c, v, count, prev_fixup, *sp;
3963   const int *subop;
3964   arelent *rptr= internal_relocs;
3965   unsigned int offset = just_count ? 0 : section->vma;
3966
3967 #define var(c)          variables[(c) - 'A']
3968 #define push(v)         (*sp++ = (v))
3969 #define pop()           (*--sp)
3970 #define emptystack()    (sp == stack)
3971
3972   som_initialize_reloc_queue (reloc_queue);
3973   memset (variables, 0, sizeof (variables));
3974   memset (stack, 0, sizeof (stack));
3975   count = 0;
3976   prev_fixup = 0;
3977   sp = stack;
3978
3979   while (fixup < end_fixups)
3980     {
3981
3982       /* Save pointer to the start of this fixup.  We'll use
3983          it later to determine if it is necessary to put this fixup
3984          on the queue.  */
3985       save_fixup = fixup;
3986
3987       /* Get the fixup code and its associated format.  */
3988       op = *fixup++;
3989       fp = &som_fixup_formats[op];
3990
3991       /* Handle a request for a previous fixup.  */
3992       if (*fp->format == 'P')
3993         {
3994           /* Get pointer to the beginning of the prev fixup, move
3995              the repeated fixup to the head of the queue.  */
3996           fixup = reloc_queue[fp->D].reloc;
3997           som_reloc_queue_fix (reloc_queue, fp->D);
3998           prev_fixup = 1;
3999
4000           /* Get the fixup code and its associated format.  */
4001           op = *fixup++;
4002           fp = &som_fixup_formats[op];
4003         }
4004
4005       /* If this fixup will be passed to BFD, set some reasonable defaults.  */
4006       if (! just_count
4007           && som_hppa_howto_table[op].type != R_NO_RELOCATION
4008           && som_hppa_howto_table[op].type != R_DATA_OVERRIDE)
4009         {
4010           rptr->address = offset;
4011           rptr->howto = &som_hppa_howto_table[op];
4012           rptr->addend = 0;
4013           rptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
4014         }
4015
4016       /* Set default input length to 0.  Get the opcode class index
4017          into D.  */
4018       var ('L') = 0;
4019       var ('D') = fp->D;
4020
4021       /* Get the opcode format.  */
4022       cp = fp->format;
4023
4024       /* Process the format string.  Parsing happens in two phases,
4025          parse RHS, then assign to LHS.  Repeat until no more 
4026          characters in the format string.  */
4027       while (*cp)
4028         {
4029           /* The variable this pass is going to compute a value for.  */
4030           varname = *cp++;
4031
4032           /* Start processing RHS.  Continue until a NULL or '=' is found.  */
4033           do
4034             {
4035               c = *cp++;
4036
4037               /* If this is a variable, push it on the stack.  */
4038               if (isupper (c))
4039                 push (var (c));
4040
4041               /* If this is a lower case letter, then it represents
4042                  additional data from the fixup stream to be pushed onto
4043                  the stack.  */
4044               else if (islower (c))
4045                 {
4046                   for (v = 0; c > 'a'; --c)
4047                     v = (v << 8) | *fixup++;
4048                   push (v);
4049                 }
4050
4051               /* A decimal constant.  Push it on the stack.  */
4052               else if (isdigit (c))
4053                 {
4054                   v = c - '0';
4055                   while (isdigit (*cp))
4056                     v = (v * 10) + (*cp++ - '0');
4057                   push (v);
4058                 }
4059               else
4060
4061                 /* An operator.  Pop two two values from the stack and
4062                    use them as operands to the given operation.  Push
4063                    the result of the operation back on the stack.  */
4064                 switch (c)
4065                   {
4066                   case '+':
4067                     v = pop ();
4068                     v += pop ();
4069                     push (v);
4070                     break;
4071                   case '*':
4072                     v = pop ();
4073                     v *= pop ();
4074                     push (v);
4075                     break;
4076                   case '<':
4077                     v = pop ();
4078                     v = pop () << v;
4079                     push (v);
4080                     break;
4081                   default:
4082                     abort ();
4083                   }
4084             }
4085           while (*cp && *cp != '=');
4086
4087           /* Move over the equal operator.  */
4088           cp++;
4089
4090           /* Pop the RHS off the stack.  */
4091           c = pop ();
4092
4093           /* Perform the assignment.  */
4094           var (varname) = c;
4095
4096           /* Handle side effects. and special 'O' stack cases.  */
4097           switch (varname)
4098             {
4099             /* Consume some bytes from the input space.  */
4100             case 'L':
4101               offset += c;
4102               break;
4103             /* A symbol to use in the relocation.  Make a note
4104                of this if we are not just counting.  */
4105             case 'S':
4106               if (! just_count)
4107                 rptr->sym_ptr_ptr = &symbols[c];
4108               break;
4109             /* Handle the linker expression stack.  */
4110             case 'O':
4111               switch (op)
4112                 {
4113                 case R_COMP1:
4114                   subop = comp1_opcodes;
4115                   break;
4116                 case R_COMP2:
4117                   subop = comp2_opcodes;
4118                   break;
4119                 case R_COMP3:
4120                   subop = comp3_opcodes;
4121                   break;
4122                 default:
4123                   abort ();
4124                 }
4125               while (*subop <= (unsigned char) c)
4126                 ++subop;
4127               --subop;
4128               break;
4129             default:
4130               break;
4131             }
4132         }
4133
4134       /* If we used a previous fixup, clean up after it.  */
4135       if (prev_fixup)
4136         {
4137           fixup = save_fixup + 1;
4138           prev_fixup = 0;
4139         }
4140       /* Queue it.  */
4141       else if (fixup > save_fixup + 1)
4142         som_reloc_queue_insert (save_fixup, fixup - save_fixup, reloc_queue);
4143
4144       /* We do not pass R_DATA_OVERRIDE or R_NO_RELOCATION 
4145          fixups to BFD.  */
4146       if (som_hppa_howto_table[op].type != R_DATA_OVERRIDE
4147           && som_hppa_howto_table[op].type != R_NO_RELOCATION)
4148         {
4149           /* Done with a single reloction. Loop back to the top.  */
4150           if (! just_count)
4151             {
4152               rptr->addend = var ('V');
4153               rptr++;
4154             }
4155           count++;
4156           /* Now that we've handled a "full" relocation, reset
4157              some state.  */
4158           memset (variables, 0, sizeof (variables));
4159           memset (stack, 0, sizeof (stack));
4160         }
4161     }
4162   return count;
4163
4164 #undef var
4165 #undef push
4166 #undef pop
4167 #undef emptystack
4168 }
4169
4170 /* Read in the relocs (aka fixups in SOM terms) for a section. 
4171
4172    som_get_reloc_upper_bound calls this routine with JUST_COUNT 
4173    set to true to indicate it only needs a count of the number
4174    of actual relocations.  */
4175
4176 static boolean
4177 som_slurp_reloc_table (abfd, section, symbols, just_count)
4178      bfd *abfd;
4179      asection *section;
4180      asymbol **symbols;
4181      boolean just_count;
4182 {
4183   char *external_relocs;
4184   unsigned int fixup_stream_size;
4185   arelent *internal_relocs;
4186   unsigned int num_relocs;
4187
4188   fixup_stream_size = som_section_data (section)->reloc_size;
4189   /* If there were no relocations, then there is nothing to do.  */
4190   if (section->reloc_count == 0)
4191     return true;
4192
4193   /* If reloc_count is -1, then the relocation stream has not been 
4194      parsed.  We must do so now to know how many relocations exist.  */
4195   if (section->reloc_count == -1)
4196     {
4197       external_relocs = (char *) malloc (fixup_stream_size);
4198       if (external_relocs == (char *) NULL)
4199         {
4200           bfd_set_error (bfd_error_no_memory);
4201           return false;
4202         }
4203       /* Read in the external forms. */
4204       if (bfd_seek (abfd,
4205                     obj_som_reloc_filepos (abfd) + section->rel_filepos,
4206                     SEEK_SET)
4207           != 0)
4208         return false;
4209       if (bfd_read (external_relocs, 1, fixup_stream_size, abfd)
4210           != fixup_stream_size)
4211         return false;
4212
4213       /* Let callers know how many relocations found.
4214          also save the relocation stream as we will
4215          need it again.  */
4216       section->reloc_count = som_set_reloc_info (external_relocs,
4217                                                  fixup_stream_size,
4218                                                  NULL, NULL, NULL, true);
4219
4220       som_section_data (section)->reloc_stream = external_relocs;
4221     }
4222
4223   /* If the caller only wanted a count, then return now.  */
4224   if (just_count)
4225     return true;
4226
4227   num_relocs = section->reloc_count;
4228   external_relocs = som_section_data (section)->reloc_stream;
4229   /* Return saved information about the relocations if it is available.  */
4230   if (section->relocation != (arelent *) NULL)
4231     return true;
4232
4233   internal_relocs = (arelent *) malloc (num_relocs * sizeof (arelent));
4234   if (internal_relocs == (arelent *) NULL)
4235     {
4236       bfd_set_error (bfd_error_no_memory);
4237       return false;
4238     }
4239
4240   /* Process and internalize the relocations.  */
4241   som_set_reloc_info (external_relocs, fixup_stream_size,
4242                       internal_relocs, section, symbols, false);
4243
4244   /* Save our results and return success.  */
4245   section->relocation = internal_relocs;
4246   return (true);
4247 }
4248
4249 /* Return the number of bytes required to store the relocation
4250    information associated with the given section.  */ 
4251
4252 static long
4253 som_get_reloc_upper_bound (abfd, asect)
4254      bfd *abfd;
4255      sec_ptr asect;
4256 {
4257   /* If section has relocations, then read in the relocation stream
4258      and parse it to determine how many relocations exist.  */
4259   if (asect->flags & SEC_RELOC)
4260     {
4261       if (! som_slurp_reloc_table (abfd, asect, NULL, true))
4262         return false;
4263       return (asect->reloc_count + 1) * sizeof (arelent);
4264     }
4265   /* There are no relocations.  */
4266   return 0;
4267 }
4268
4269 /* Convert relocations from SOM (external) form into BFD internal
4270    form.  Return the number of relocations.  */
4271
4272 static long
4273 som_canonicalize_reloc (abfd, section, relptr, symbols)
4274      bfd *abfd;
4275      sec_ptr section;
4276      arelent **relptr;
4277      asymbol **symbols;
4278 {
4279   arelent *tblptr;
4280   int count;
4281
4282   if (som_slurp_reloc_table (abfd, section, symbols, false) == false)
4283     return -1;
4284
4285   count = section->reloc_count;
4286   tblptr = section->relocation;
4287
4288   while (count--)
4289     *relptr++ = tblptr++;
4290
4291   *relptr = (arelent *) NULL;
4292   return section->reloc_count;
4293 }
4294
4295 extern const bfd_target som_vec;
4296
4297 /* A hook to set up object file dependent section information.  */
4298
4299 static boolean
4300 som_new_section_hook (abfd, newsect)
4301      bfd *abfd;
4302      asection *newsect;
4303 {
4304   newsect->used_by_bfd =
4305     (PTR) bfd_zalloc (abfd, sizeof (struct som_section_data_struct));
4306   if (!newsect->used_by_bfd)
4307     {
4308       bfd_set_error (bfd_error_no_memory);
4309       return false;
4310     }
4311   newsect->alignment_power = 3;
4312
4313   /* We allow more than three sections internally */
4314   return true;
4315 }
4316
4317 /* Copy any private info we understand from the input section
4318    to the output section.  */
4319 static boolean
4320 som_bfd_copy_private_section_data (ibfd, isection, obfd, osection)
4321      bfd *ibfd;
4322      asection *isection;
4323      bfd *obfd;
4324      asection *osection;
4325 {
4326   /* One day we may try to grok other private data.  */
4327   if (ibfd->xvec->flavour != bfd_target_som_flavour
4328       || obfd->xvec->flavour != bfd_target_som_flavour
4329       || (!som_is_space (isection) && !som_is_subspace (isection)))
4330     return false;
4331
4332   som_section_data (osection)->copy_data
4333     = (struct som_copyable_section_data_struct *)
4334       bfd_zalloc (obfd, sizeof (struct som_copyable_section_data_struct));
4335   if (som_section_data (osection)->copy_data == NULL)
4336     {
4337       bfd_set_error (bfd_error_no_memory);
4338       return false;
4339     }
4340
4341   memcpy (som_section_data (osection)->copy_data,
4342           som_section_data (isection)->copy_data,
4343           sizeof (struct som_copyable_section_data_struct));
4344
4345   /* Reparent if necessary.  */
4346   if (som_section_data (osection)->copy_data->container)
4347     som_section_data (osection)->copy_data->container =
4348       som_section_data (osection)->copy_data->container->output_section;
4349
4350   return true;
4351 }
4352
4353 /* Copy any private info we understand from the input bfd
4354    to the output bfd.  */
4355
4356 static boolean
4357 som_bfd_copy_private_bfd_data (ibfd, obfd)
4358      bfd *ibfd, *obfd;
4359 {
4360   /* One day we may try to grok other private data.  */
4361   if (ibfd->xvec->flavour != bfd_target_som_flavour
4362       || obfd->xvec->flavour != bfd_target_som_flavour)
4363     return false;
4364
4365   /* Allocate some memory to hold the data we need.  */
4366   obj_som_exec_data (obfd) = (struct som_exec_data *)
4367     bfd_zalloc (obfd, sizeof (struct som_exec_data));
4368   if (obj_som_exec_data (obfd) == NULL)
4369     {
4370       bfd_set_error (bfd_error_no_memory);
4371       return false;
4372     }
4373
4374   /* Now copy the data.  */
4375   memcpy (obj_som_exec_data (obfd), obj_som_exec_data (ibfd),
4376           sizeof (struct som_exec_data));
4377
4378   return true;
4379 }
4380
4381 /* Set backend info for sections which can not be described
4382    in the BFD data structures.  */
4383
4384 boolean
4385 bfd_som_set_section_attributes (section, defined, private, sort_key, spnum)
4386      asection *section;
4387      int defined;
4388      int private;
4389      unsigned int sort_key;
4390      int spnum;
4391 {
4392   /* Allocate memory to hold the magic information.  */
4393   if (som_section_data (section)->copy_data == NULL)
4394     {
4395       som_section_data (section)->copy_data
4396         = (struct som_copyable_section_data_struct *)
4397           bfd_zalloc (section->owner,
4398                       sizeof (struct som_copyable_section_data_struct));
4399       if (som_section_data (section)->copy_data == NULL)
4400         {
4401           bfd_set_error (bfd_error_no_memory);
4402           return false;
4403         }
4404     }
4405   som_section_data (section)->copy_data->sort_key = sort_key;
4406   som_section_data (section)->copy_data->is_defined = defined;
4407   som_section_data (section)->copy_data->is_private = private;
4408   som_section_data (section)->copy_data->container = section;
4409   som_section_data (section)->copy_data->space_number = spnum;
4410   return true;
4411 }
4412
4413 /* Set backend info for subsections which can not be described 
4414    in the BFD data structures.  */
4415
4416 boolean
4417 bfd_som_set_subsection_attributes (section, container, access,
4418                                    sort_key, quadrant)
4419      asection *section;
4420      asection *container;
4421      int access;
4422      unsigned int sort_key;
4423      int quadrant;
4424 {
4425   /* Allocate memory to hold the magic information.  */
4426   if (som_section_data (section)->copy_data == NULL)
4427     {
4428       som_section_data (section)->copy_data
4429         = (struct som_copyable_section_data_struct *)
4430           bfd_zalloc (section->owner,
4431                       sizeof (struct som_copyable_section_data_struct));
4432       if (som_section_data (section)->copy_data == NULL)
4433         {
4434           bfd_set_error (bfd_error_no_memory);
4435           return false;
4436         }
4437     }
4438   som_section_data (section)->copy_data->sort_key = sort_key;
4439   som_section_data (section)->copy_data->access_control_bits = access;
4440   som_section_data (section)->copy_data->quadrant = quadrant;
4441   som_section_data (section)->copy_data->container = container;
4442   return true;
4443 }
4444
4445 /* Set the full SOM symbol type.  SOM needs far more symbol information
4446    than any other object file format I'm aware of.  It is mandatory
4447    to be able to know if a symbol is an entry point, millicode, data,
4448    code, absolute, storage request, or procedure label.  If you get
4449    the symbol type wrong your program will not link.  */
4450
4451 void
4452 bfd_som_set_symbol_type (symbol, type)
4453      asymbol *symbol;
4454      unsigned int type;
4455 {
4456   som_symbol_data (symbol)->som_type = type;
4457 }
4458
4459 /* Attach 64bits of unwind information to a symbol (which hopefully
4460    is a function of some kind!).  It would be better to keep this
4461    in the R_ENTRY relocation, but there is not enough space.  */
4462
4463 void
4464 bfd_som_attach_unwind_info (symbol, unwind_desc)
4465      asymbol *symbol;
4466      char *unwind_desc;
4467 {
4468   som_symbol_data (symbol)->unwind = unwind_desc;
4469 }
4470
4471 /* Attach an auxiliary header to the BFD backend so that it may be
4472    written into the object file.  */
4473 boolean
4474 bfd_som_attach_aux_hdr (abfd, type, string)
4475      bfd *abfd;
4476      int type;
4477      char *string;
4478 {
4479   if (type == VERSION_AUX_ID)
4480     {
4481       int len = strlen (string);
4482       int pad = 0;
4483
4484       if (len % 4)
4485         pad = (4 - (len % 4));
4486       obj_som_version_hdr (abfd) = (struct user_string_aux_hdr *)
4487         bfd_zalloc (abfd, sizeof (struct aux_id)
4488                               + sizeof (unsigned int) + len + pad);
4489       if (!obj_som_version_hdr (abfd))
4490         {
4491           bfd_set_error (bfd_error_no_memory);
4492           return false;
4493         }
4494       obj_som_version_hdr (abfd)->header_id.type = VERSION_AUX_ID;
4495       obj_som_version_hdr (abfd)->header_id.length = len + pad;
4496       obj_som_version_hdr (abfd)->header_id.length += sizeof (int);
4497       obj_som_version_hdr (abfd)->string_length = len;
4498       strncpy (obj_som_version_hdr (abfd)->user_string, string, len);
4499     }
4500   else if (type == COPYRIGHT_AUX_ID)
4501     {
4502       int len = strlen (string);
4503       int pad = 0;
4504
4505       if (len % 4)
4506         pad = (4 - (len % 4));
4507       obj_som_copyright_hdr (abfd) = (struct copyright_aux_hdr *)
4508         bfd_zalloc (abfd, sizeof (struct aux_id)
4509                             + sizeof (unsigned int) + len + pad);
4510       if (!obj_som_copyright_hdr (abfd))
4511         {
4512           bfd_set_error (bfd_error_no_memory);
4513           return false;
4514         }
4515       obj_som_copyright_hdr (abfd)->header_id.type = COPYRIGHT_AUX_ID;
4516       obj_som_copyright_hdr (abfd)->header_id.length = len + pad;
4517       obj_som_copyright_hdr (abfd)->header_id.length += sizeof (int);
4518       obj_som_copyright_hdr (abfd)->string_length = len;
4519       strcpy (obj_som_copyright_hdr (abfd)->copyright, string);
4520     }
4521   return true;
4522 }
4523
4524 static boolean
4525 som_get_section_contents (abfd, section, location, offset, count)
4526      bfd *abfd;
4527      sec_ptr section;
4528      PTR location;
4529      file_ptr offset;
4530      bfd_size_type count;
4531 {
4532   if (count == 0 || ((section->flags & (SEC_LOAD | SEC_DEBUGGING)) == 0))
4533     return true;
4534   if ((bfd_size_type)(offset+count) > section->_raw_size
4535       || bfd_seek (abfd, (file_ptr)(section->filepos + offset), SEEK_SET) == -1
4536       || bfd_read (location, (bfd_size_type)1, count, abfd) != count)
4537     return (false); /* on error */
4538   return (true);
4539 }
4540
4541 static boolean
4542 som_set_section_contents (abfd, section, location, offset, count)
4543      bfd *abfd;
4544      sec_ptr section;
4545      PTR location;
4546      file_ptr offset;
4547      bfd_size_type count;
4548 {
4549   if (abfd->output_has_begun == false)
4550     {
4551       /* Set up fixed parts of the file, space, and subspace headers.
4552          Notify the world that output has begun.  */
4553       som_prep_headers (abfd);
4554       abfd->output_has_begun = true;
4555       /* Start writing the object file.  This include all the string
4556          tables, fixup streams, and other portions of the object file.  */
4557       som_begin_writing (abfd);
4558     }
4559
4560   /* Only write subspaces which have "real" contents (eg. the contents
4561      are not generated at run time by the OS).  */
4562   if (!som_is_subspace (section)
4563       || ((section->flags & (SEC_LOAD | SEC_DEBUGGING)) == 0))
4564     return true;
4565
4566   /* Seek to the proper offset within the object file and write the
4567      data.  */
4568   offset += som_section_data (section)->subspace_dict->file_loc_init_value; 
4569   if (bfd_seek (abfd, offset, SEEK_SET) == -1)
4570     return false;
4571
4572   if (bfd_write ((PTR) location, 1, count, abfd) != count)
4573     return false;
4574   return true;
4575 }
4576
4577 static boolean
4578 som_set_arch_mach (abfd, arch, machine)
4579      bfd *abfd;
4580      enum bfd_architecture arch;
4581      unsigned long machine;
4582 {
4583   /* Allow any architecture to be supported by the SOM backend */
4584   return bfd_default_set_arch_mach (abfd, arch, machine);
4585 }
4586
4587 static boolean
4588 som_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
4589                         functionname_ptr, line_ptr)
4590      bfd *abfd;
4591      asection *section;
4592      asymbol **symbols;
4593      bfd_vma offset;
4594      CONST char **filename_ptr;
4595      CONST char **functionname_ptr;
4596      unsigned int *line_ptr;
4597 {
4598   fprintf (stderr, "som_find_nearest_line unimplemented\n");
4599   fflush (stderr);
4600   abort ();
4601   return (false);
4602 }
4603
4604 static int
4605 som_sizeof_headers (abfd, reloc)
4606      bfd *abfd;
4607      boolean reloc;
4608 {
4609   fprintf (stderr, "som_sizeof_headers unimplemented\n");
4610   fflush (stderr);
4611   abort ();
4612   return (0);
4613 }
4614
4615 /* Return the single-character symbol type corresponding to
4616    SOM section S, or '?' for an unknown SOM section.  */
4617
4618 static char
4619 som_section_type (s)
4620      const char *s;
4621 {
4622   const struct section_to_type *t;
4623
4624   for (t = &stt[0]; t->section; t++)
4625     if (!strcmp (s, t->section))
4626       return t->type;
4627   return '?';
4628 }
4629
4630 static int
4631 som_decode_symclass (symbol)
4632      asymbol *symbol;
4633 {
4634   char c;
4635
4636   if (bfd_is_com_section (symbol->section))
4637     return 'C';
4638   if (bfd_is_und_section (symbol->section))
4639     return 'U';
4640   if (bfd_is_ind_section (symbol->section))
4641     return 'I';
4642   if (!(symbol->flags & (BSF_GLOBAL|BSF_LOCAL)))
4643     return '?';
4644
4645   if (bfd_is_abs_section (symbol->section))
4646     c = 'a';
4647   else if (symbol->section)
4648     c = som_section_type (symbol->section->name);
4649   else
4650     return '?';
4651   if (symbol->flags & BSF_GLOBAL)
4652     c = toupper (c);
4653   return c;
4654 }
4655
4656 /* Return information about SOM symbol SYMBOL in RET.  */
4657
4658 static void
4659 som_get_symbol_info (ignore_abfd, symbol, ret)
4660      bfd *ignore_abfd;
4661      asymbol *symbol;
4662      symbol_info *ret;
4663 {
4664   ret->type = som_decode_symclass (symbol);
4665   if (ret->type != 'U')
4666     ret->value = symbol->value+symbol->section->vma;
4667   else
4668     ret->value = 0;
4669   ret->name = symbol->name;
4670 }
4671
4672 /* Count the number of symbols in the archive symbol table.  Necessary
4673    so that we can allocate space for all the carsyms at once.  */
4674
4675 static boolean
4676 som_bfd_count_ar_symbols (abfd, lst_header, count)
4677      bfd *abfd;
4678      struct lst_header *lst_header;
4679      symindex *count;
4680 {
4681   unsigned int i;
4682   unsigned int *hash_table = NULL;
4683   file_ptr lst_filepos = bfd_tell (abfd) - sizeof (struct lst_header);
4684
4685   hash_table = 
4686     (unsigned int *) malloc (lst_header->hash_size * sizeof (unsigned int));
4687   if (hash_table == NULL && lst_header->hash_size != 0)
4688     {
4689       bfd_set_error (bfd_error_no_memory);
4690       goto error_return;
4691     }
4692
4693   /* Don't forget to initialize the counter!  */
4694   *count = 0;
4695
4696   /* Read in the hash table.  The has table is an array of 32bit file offsets
4697      which point to the hash chains.  */
4698   if (bfd_read ((PTR) hash_table, lst_header->hash_size, 4, abfd)
4699       != lst_header->hash_size * 4)
4700     goto error_return;
4701
4702   /* Walk each chain counting the number of symbols found on that particular
4703      chain.  */
4704   for (i = 0; i < lst_header->hash_size; i++)
4705     {
4706       struct lst_symbol_record lst_symbol;
4707
4708       /* An empty chain has zero as it's file offset.  */
4709       if (hash_table[i] == 0)
4710         continue;
4711
4712       /* Seek to the first symbol in this hash chain.  */
4713       if (bfd_seek (abfd, lst_filepos + hash_table[i], SEEK_SET) < 0)
4714         goto error_return;
4715
4716       /* Read in this symbol and update the counter.  */
4717       if (bfd_read ((PTR) & lst_symbol, 1, sizeof (lst_symbol), abfd)
4718           != sizeof (lst_symbol))
4719         goto error_return;
4720
4721       (*count)++;
4722
4723       /* Now iterate through the rest of the symbols on this chain.  */
4724       while (lst_symbol.next_entry)
4725         {
4726
4727           /* Seek to the next symbol.  */
4728           if (bfd_seek (abfd, lst_filepos + lst_symbol.next_entry, SEEK_SET)
4729               < 0)
4730             goto error_return;
4731
4732           /* Read the symbol in and update the counter.  */
4733           if (bfd_read ((PTR) & lst_symbol, 1, sizeof (lst_symbol), abfd)
4734               != sizeof (lst_symbol))
4735             goto error_return;
4736
4737           (*count)++;
4738         }
4739     }
4740   if (hash_table != NULL)
4741     free (hash_table);
4742   return true;
4743
4744  error_return:
4745   if (hash_table != NULL)
4746     free (hash_table);
4747   return false;
4748 }
4749
4750 /* Fill in the canonical archive symbols (SYMS) from the archive described
4751    by ABFD and LST_HEADER.  */
4752
4753 static boolean
4754 som_bfd_fill_in_ar_symbols (abfd, lst_header, syms)
4755      bfd *abfd;
4756      struct lst_header *lst_header;
4757      carsym **syms;
4758 {
4759   unsigned int i, len;
4760   carsym *set = syms[0];
4761   unsigned int *hash_table = NULL;
4762   struct som_entry *som_dict = NULL;
4763   file_ptr lst_filepos = bfd_tell (abfd) - sizeof (struct lst_header);
4764
4765   hash_table = 
4766     (unsigned int *) malloc (lst_header->hash_size * sizeof (unsigned int));
4767   if (hash_table == NULL && lst_header->hash_size != 0)
4768     {
4769       bfd_set_error (bfd_error_no_memory);
4770       goto error_return;
4771     }
4772
4773   som_dict =
4774     (struct som_entry *) malloc (lst_header->module_count
4775                                  * sizeof (struct som_entry));
4776   if (som_dict == NULL && lst_header->module_count != 0)
4777     {
4778       bfd_set_error (bfd_error_no_memory);
4779       goto error_return;
4780     }
4781
4782   /* Read in the hash table.  The has table is an array of 32bit file offsets
4783      which point to the hash chains.  */
4784   if (bfd_read ((PTR) hash_table, lst_header->hash_size, 4, abfd)
4785       != lst_header->hash_size * 4)
4786     goto error_return;
4787
4788   /* Seek to and read in the SOM dictionary.  We will need this to fill
4789      in the carsym's filepos field.  */
4790   if (bfd_seek (abfd, lst_filepos + lst_header->dir_loc, SEEK_SET) < 0)
4791     goto error_return;
4792
4793   if (bfd_read ((PTR) som_dict, lst_header->module_count, 
4794                 sizeof (struct som_entry), abfd)
4795       != lst_header->module_count * sizeof (struct som_entry))
4796     goto error_return;
4797
4798   /* Walk each chain filling in the carsyms as we go along.  */
4799   for (i = 0; i < lst_header->hash_size; i++)
4800     {
4801       struct lst_symbol_record lst_symbol;
4802
4803       /* An empty chain has zero as it's file offset.  */
4804       if (hash_table[i] == 0)
4805         continue;
4806
4807       /* Seek to and read the first symbol on the chain.  */
4808       if (bfd_seek (abfd, lst_filepos + hash_table[i], SEEK_SET) < 0)
4809         goto error_return;
4810
4811       if (bfd_read ((PTR) & lst_symbol, 1, sizeof (lst_symbol), abfd)
4812           != sizeof (lst_symbol))
4813         goto error_return;
4814
4815       /* Get the name of the symbol, first get the length which is stored
4816          as a 32bit integer just before the symbol.
4817
4818          One might ask why we don't just read in the entire string table
4819          and index into it.  Well, according to the SOM ABI the string
4820          index can point *anywhere* in the archive to save space, so just
4821          using the string table would not be safe.  */
4822       if (bfd_seek (abfd, lst_filepos + lst_header->string_loc
4823                             + lst_symbol.name.n_strx - 4, SEEK_SET) < 0)
4824         goto error_return;
4825
4826       if (bfd_read (&len, 1, 4, abfd) != 4)
4827         goto error_return;
4828
4829       /* Allocate space for the name and null terminate it too.  */
4830       set->name = bfd_zalloc (abfd, len + 1);
4831       if (!set->name)
4832         {
4833           bfd_set_error (bfd_error_no_memory);
4834           goto error_return;
4835         }
4836       if (bfd_read (set->name, 1, len, abfd) != len)
4837         goto error_return;
4838
4839       set->name[len] = 0;
4840
4841       /* Fill in the file offset.  Note that the "location" field points
4842          to the SOM itself, not the ar_hdr in front of it.  */
4843       set->file_offset = som_dict[lst_symbol.som_index].location
4844                           - sizeof (struct ar_hdr);
4845
4846       /* Go to the next symbol.  */
4847       set++;
4848
4849       /* Iterate through the rest of the chain.  */
4850       while (lst_symbol.next_entry)
4851         {
4852           /* Seek to the next symbol and read it in.  */
4853           if (bfd_seek (abfd, lst_filepos + lst_symbol.next_entry, SEEK_SET) <0)
4854             goto error_return;
4855
4856           if (bfd_read ((PTR) & lst_symbol, 1, sizeof (lst_symbol), abfd)
4857               != sizeof (lst_symbol))
4858             goto error_return;
4859
4860           /* Seek to the name length & string and read them in.  */
4861           if (bfd_seek (abfd, lst_filepos + lst_header->string_loc 
4862                                 + lst_symbol.name.n_strx - 4, SEEK_SET) < 0)
4863             goto error_return;
4864
4865           if (bfd_read (&len, 1, 4, abfd) != 4)
4866             goto error_return;
4867
4868           /* Allocate space for the name and null terminate it too.  */
4869           set->name = bfd_zalloc (abfd, len + 1);
4870           if (!set->name)
4871             {
4872               bfd_set_error (bfd_error_no_memory);
4873               goto error_return;
4874             }
4875
4876           if (bfd_read (set->name, 1, len, abfd) != len)
4877             goto error_return;
4878           set->name[len] = 0;
4879
4880           /* Fill in the file offset.  Note that the "location" field points
4881              to the SOM itself, not the ar_hdr in front of it.  */
4882           set->file_offset = som_dict[lst_symbol.som_index].location
4883                                - sizeof (struct ar_hdr);
4884
4885           /* Go on to the next symbol.  */
4886           set++;
4887         }
4888     }
4889   /* If we haven't died by now, then we successfully read the entire 
4890      archive symbol table.  */
4891   if (hash_table != NULL)
4892     free (hash_table);
4893   if (som_dict != NULL)
4894     free (som_dict);
4895   return true;
4896
4897  error_return:
4898   if (hash_table != NULL)
4899     free (hash_table);
4900   if (som_dict != NULL)
4901     free (som_dict);
4902   return false;
4903 }
4904
4905 /* Read in the LST from the archive.  */
4906 static boolean
4907 som_slurp_armap (abfd)
4908      bfd *abfd;
4909 {
4910   struct lst_header lst_header;
4911   struct ar_hdr ar_header;
4912   unsigned int parsed_size;
4913   struct artdata *ardata = bfd_ardata (abfd);
4914   char nextname[17];
4915   int i = bfd_read ((PTR) nextname, 1, 16, abfd);
4916
4917   /* Special cases.  */
4918   if (i == 0)
4919     return true;
4920   if (i != 16)
4921     return false;
4922
4923   if (bfd_seek (abfd, (file_ptr) - 16, SEEK_CUR) < 0)
4924     return false;
4925
4926   /* For archives without .o files there is no symbol table.  */
4927   if (strncmp (nextname, "/               ", 16))
4928     {
4929       bfd_has_map (abfd) = false;
4930       return true;
4931     }
4932
4933   /* Read in and sanity check the archive header.  */
4934   if (bfd_read ((PTR) &ar_header, 1, sizeof (struct ar_hdr), abfd)
4935       != sizeof (struct ar_hdr))
4936     return false;
4937
4938   if (strncmp (ar_header.ar_fmag, ARFMAG, 2))
4939     {
4940       bfd_set_error (bfd_error_malformed_archive);
4941       return false;
4942     }
4943
4944   /* How big is the archive symbol table entry?  */
4945   errno = 0;
4946   parsed_size = strtol (ar_header.ar_size, NULL, 10);
4947   if (errno != 0)
4948     {
4949       bfd_set_error (bfd_error_malformed_archive);
4950       return false;
4951     }
4952
4953   /* Save off the file offset of the first real user data.  */
4954   ardata->first_file_filepos = bfd_tell (abfd) + parsed_size;
4955
4956   /* Read in the library symbol table.  We'll make heavy use of this
4957      in just a minute.  */
4958   if (bfd_read ((PTR) & lst_header, 1, sizeof (struct lst_header), abfd)
4959       != sizeof (struct lst_header))
4960     return false;
4961
4962   /* Sanity check.  */
4963   if (lst_header.a_magic != LIBMAGIC)
4964     {
4965       bfd_set_error (bfd_error_malformed_archive);
4966       return false;
4967     }
4968
4969   /* Count the number of symbols in the library symbol table.  */
4970   if (som_bfd_count_ar_symbols (abfd, &lst_header, &ardata->symdef_count)
4971       == false)
4972     return false;
4973
4974   /* Get back to the start of the library symbol table.  */
4975   if (bfd_seek (abfd, ardata->first_file_filepos - parsed_size 
4976                         + sizeof (struct lst_header), SEEK_SET) < 0)
4977     return false;
4978
4979   /* Initializae the cache and allocate space for the library symbols.  */
4980   ardata->cache = 0;
4981   ardata->symdefs = (carsym *) bfd_alloc (abfd,
4982                                           (ardata->symdef_count
4983                                            * sizeof (carsym)));
4984   if (!ardata->symdefs)
4985     {
4986       bfd_set_error (bfd_error_no_memory);
4987       return false;
4988     }
4989
4990   /* Now fill in the canonical archive symbols.  */
4991   if (som_bfd_fill_in_ar_symbols (abfd, &lst_header, &ardata->symdefs)
4992       == false)
4993     return false;
4994
4995   /* Seek back to the "first" file in the archive.  Note the "first"
4996      file may be the extended name table.  */
4997   if (bfd_seek (abfd, ardata->first_file_filepos, SEEK_SET) < 0)
4998     return false;
4999
5000   /* Notify the generic archive code that we have a symbol map.  */
5001   bfd_has_map (abfd) = true;
5002   return true;
5003 }
5004
5005 /* Begin preparing to write a SOM library symbol table.
5006
5007    As part of the prep work we need to determine the number of symbols
5008    and the size of the associated string section.  */
5009
5010 static boolean
5011 som_bfd_prep_for_ar_write (abfd, num_syms, stringsize)
5012      bfd *abfd;
5013      unsigned int *num_syms, *stringsize;
5014 {
5015   bfd *curr_bfd = abfd->archive_head;
5016
5017   /* Some initialization.  */
5018   *num_syms = 0;
5019   *stringsize = 0;
5020
5021   /* Iterate over each BFD within this archive.  */
5022   while (curr_bfd != NULL)
5023     {
5024       unsigned int curr_count, i;
5025       som_symbol_type *sym;
5026
5027       /* Don't bother for non-SOM objects.  */
5028       if (curr_bfd->format != bfd_object
5029           || curr_bfd->xvec->flavour != bfd_target_som_flavour)
5030         {
5031           curr_bfd = curr_bfd->next;
5032           continue;
5033         }
5034
5035       /* Make sure the symbol table has been read, then snag a pointer
5036          to it.  It's a little slimey to grab the symbols via obj_som_symtab,
5037          but doing so avoids allocating lots of extra memory.  */
5038       if (som_slurp_symbol_table (curr_bfd) == false)
5039         return false;
5040
5041       sym = obj_som_symtab (curr_bfd);
5042       curr_count = bfd_get_symcount (curr_bfd);
5043
5044       /* Examine each symbol to determine if it belongs in the
5045          library symbol table.  */
5046       for (i = 0; i < curr_count; i++, sym++)
5047         {
5048           struct som_misc_symbol_info info;
5049
5050           /* Derive SOM information from the BFD symbol.  */
5051           som_bfd_derive_misc_symbol_info (curr_bfd, &sym->symbol, &info);
5052
5053           /* Should we include this symbol?  */
5054           if (info.symbol_type == ST_NULL
5055               || info.symbol_type == ST_SYM_EXT
5056               || info.symbol_type == ST_ARG_EXT)
5057             continue;
5058
5059           /* Only global symbols and unsatisfied commons.  */
5060           if (info.symbol_scope != SS_UNIVERSAL
5061               && info.symbol_type != ST_STORAGE)
5062             continue;
5063
5064           /* Do no include undefined symbols.  */
5065           if (bfd_is_und_section (sym->symbol.section))
5066             continue;
5067
5068           /* Bump the various counters, being careful to honor
5069              alignment considerations in the string table.  */
5070           (*num_syms)++;
5071           *stringsize = *stringsize + strlen (sym->symbol.name) + 5;
5072           while (*stringsize % 4)
5073             (*stringsize)++;
5074         }
5075
5076       curr_bfd = curr_bfd->next;
5077     }
5078   return true;
5079 }
5080
5081 /* Hash a symbol name based on the hashing algorithm presented in the
5082    SOM ABI.  */
5083 static unsigned int
5084 som_bfd_ar_symbol_hash (symbol)
5085      asymbol *symbol;
5086 {
5087   unsigned int len = strlen (symbol->name);
5088
5089   /* Names with length 1 are special.  */
5090   if (len == 1)
5091     return 0x1000100 | (symbol->name[0] << 16) | symbol->name[0];
5092
5093   return ((len & 0x7f) << 24) | (symbol->name[1] << 16)
5094           | (symbol->name[len-2] << 8) | symbol->name[len-1];
5095 }
5096
5097 static CONST char *
5098 normalize (file)
5099      CONST char *file;
5100 {
5101   CONST char *filename = strrchr (file, '/');
5102
5103   if (filename != NULL)
5104     filename++;
5105   else
5106     filename = file;
5107   return filename;
5108 }
5109
5110 /* Do the bulk of the work required to write the SOM library
5111    symbol table.  */
5112    
5113 static boolean
5114 som_bfd_ar_write_symbol_stuff (abfd, nsyms, string_size, lst)
5115      bfd *abfd;
5116      unsigned int nsyms, string_size;
5117      struct lst_header lst;
5118 {
5119   file_ptr lst_filepos;
5120   char *strings = NULL, *p;
5121   struct lst_symbol_record *lst_syms = NULL, *curr_lst_sym;
5122   bfd *curr_bfd;
5123   unsigned int *hash_table = NULL;
5124   struct som_entry *som_dict = NULL;
5125   struct lst_symbol_record **last_hash_entry = NULL;
5126   unsigned int curr_som_offset, som_index, extended_name_length = 0;
5127   unsigned int maxname = abfd->xvec->ar_max_namelen;
5128
5129   hash_table =
5130     (unsigned int *) malloc (lst.hash_size * sizeof (unsigned int));
5131   if (hash_table == NULL && lst.hash_size != 0)
5132     {
5133       bfd_set_error (bfd_error_no_memory);
5134       goto error_return;
5135     }
5136   som_dict =
5137     (struct som_entry *) malloc (lst.module_count
5138                                  * sizeof (struct som_entry));
5139   if (som_dict == NULL && lst.module_count != 0)
5140     {
5141       bfd_set_error (bfd_error_no_memory);
5142       goto error_return;
5143     }
5144
5145   last_hash_entry =
5146     ((struct lst_symbol_record **)
5147      malloc (lst.hash_size * sizeof (struct lst_symbol_record *)));
5148   if (last_hash_entry == NULL && lst.hash_size != 0)
5149     {
5150       bfd_set_error (bfd_error_no_memory);
5151       goto error_return;
5152     }
5153
5154   /* Lots of fields are file positions relative to the start
5155      of the lst record.  So save its location.  */
5156   lst_filepos = bfd_tell (abfd) - sizeof (struct lst_header);
5157
5158   /* Some initialization.  */
5159   memset (hash_table, 0, 4 * lst.hash_size);
5160   memset (som_dict, 0, lst.module_count * sizeof (struct som_entry));
5161   memset (last_hash_entry, 0,   
5162           lst.hash_size * sizeof (struct lst_symbol_record *));
5163
5164   /* Symbols have som_index fields, so we have to keep track of the
5165      index of each SOM in the archive.
5166
5167      The SOM dictionary has (among other things) the absolute file
5168      position for the SOM which a particular dictionary entry
5169      describes.  We have to compute that information as we iterate
5170      through the SOMs/symbols.  */
5171   som_index = 0;
5172   curr_som_offset = 8 + 2 * sizeof (struct ar_hdr) + lst.file_end;
5173
5174   /* Yow!  We have to know the size of the extended name table
5175      too.  */
5176   for (curr_bfd = abfd->archive_head;
5177        curr_bfd != NULL;
5178        curr_bfd = curr_bfd->next)
5179     {
5180       CONST char *normal = normalize (curr_bfd->filename);
5181       unsigned int thislen;
5182
5183       if (!normal)
5184         {
5185           bfd_set_error (bfd_error_no_memory);
5186           return false;
5187         }
5188       thislen = strlen (normal);
5189       if (thislen > maxname)
5190         extended_name_length += thislen + 1;
5191     }
5192
5193   /* Make room for the archive header and the contents of the
5194      extended string table.  */
5195   if (extended_name_length)
5196     curr_som_offset += extended_name_length + sizeof (struct ar_hdr);
5197
5198   /* Make sure we're properly aligned.  */
5199   curr_som_offset = (curr_som_offset + 0x1) & ~0x1;
5200
5201   /* FIXME should be done with buffers just like everything else... */
5202   lst_syms = malloc (nsyms * sizeof (struct lst_symbol_record));
5203   if (lst_syms == NULL && nsyms != 0)
5204     {
5205       bfd_set_error (bfd_error_no_memory);
5206       goto error_return;
5207     }
5208   strings = malloc (string_size);
5209   if (strings == NULL && string_size != 0)
5210     {
5211       bfd_set_error (bfd_error_no_memory);
5212       goto error_return;
5213     }
5214
5215   p = strings;
5216   curr_lst_sym = lst_syms;
5217
5218   curr_bfd = abfd->archive_head;
5219   while (curr_bfd != NULL)
5220     {
5221       unsigned int curr_count, i;
5222       som_symbol_type *sym;
5223
5224       /* Don't bother for non-SOM objects.  */
5225       if (curr_bfd->format != bfd_object
5226           || curr_bfd->xvec->flavour != bfd_target_som_flavour)
5227         {
5228           curr_bfd = curr_bfd->next;
5229           continue;
5230         }
5231
5232       /* Make sure the symbol table has been read, then snag a pointer
5233          to it.  It's a little slimey to grab the symbols via obj_som_symtab,
5234          but doing so avoids allocating lots of extra memory.  */
5235       if (som_slurp_symbol_table (curr_bfd) == false)
5236         goto error_return;
5237
5238       sym = obj_som_symtab (curr_bfd);
5239       curr_count = bfd_get_symcount (curr_bfd);
5240
5241       for (i = 0; i < curr_count; i++, sym++)
5242         {
5243           struct som_misc_symbol_info info;
5244
5245           /* Derive SOM information from the BFD symbol.  */
5246           som_bfd_derive_misc_symbol_info (curr_bfd, &sym->symbol, &info);
5247
5248           /* Should we include this symbol?  */
5249           if (info.symbol_type == ST_NULL
5250               || info.symbol_type == ST_SYM_EXT
5251               || info.symbol_type == ST_ARG_EXT)
5252             continue;
5253
5254           /* Only global symbols and unsatisfied commons.  */
5255           if (info.symbol_scope != SS_UNIVERSAL
5256               && info.symbol_type != ST_STORAGE)
5257             continue;
5258
5259           /* Do no include undefined symbols.  */
5260           if (bfd_is_und_section (sym->symbol.section))
5261             continue;
5262
5263           /* If this is the first symbol from this SOM, then update
5264              the SOM dictionary too.  */
5265           if (som_dict[som_index].location == 0)
5266             {
5267               som_dict[som_index].location = curr_som_offset;
5268               som_dict[som_index].length = arelt_size (curr_bfd);
5269             }
5270
5271           /* Fill in the lst symbol record.  */
5272           curr_lst_sym->hidden = 0;
5273           curr_lst_sym->secondary_def = 0;
5274           curr_lst_sym->symbol_type = info.symbol_type;
5275           curr_lst_sym->symbol_scope = info.symbol_scope;
5276           curr_lst_sym->check_level = 0;
5277           curr_lst_sym->must_qualify = 0;
5278           curr_lst_sym->initially_frozen = 0;
5279           curr_lst_sym->memory_resident = 0;
5280           curr_lst_sym->is_common = bfd_is_com_section (sym->symbol.section);
5281           curr_lst_sym->dup_common = 0;
5282           curr_lst_sym->xleast = 0;
5283           curr_lst_sym->arg_reloc = info.arg_reloc;
5284           curr_lst_sym->name.n_strx = p - strings + 4;
5285           curr_lst_sym->qualifier_name.n_strx = 0;
5286           curr_lst_sym->symbol_info = info.symbol_info;
5287           curr_lst_sym->symbol_value = info.symbol_value;
5288           curr_lst_sym->symbol_descriptor = 0;
5289           curr_lst_sym->reserved = 0;
5290           curr_lst_sym->som_index = som_index;
5291           curr_lst_sym->symbol_key = som_bfd_ar_symbol_hash (&sym->symbol);
5292           curr_lst_sym->next_entry = 0;
5293
5294           /* Insert into the hash table.  */
5295           if (hash_table[curr_lst_sym->symbol_key % lst.hash_size])
5296             {
5297               struct lst_symbol_record *tmp;
5298
5299               /* There is already something at the head of this hash chain,
5300                  so tack this symbol onto the end of the chain.  */
5301               tmp = last_hash_entry[curr_lst_sym->symbol_key % lst.hash_size];
5302               tmp->next_entry
5303                 = (curr_lst_sym - lst_syms) * sizeof (struct lst_symbol_record)
5304                   + lst.hash_size * 4 
5305                   + lst.module_count * sizeof (struct som_entry)
5306                   + sizeof (struct lst_header);
5307             }
5308           else
5309             {
5310               /* First entry in this hash chain.  */
5311               hash_table[curr_lst_sym->symbol_key % lst.hash_size]
5312                 = (curr_lst_sym - lst_syms) * sizeof (struct lst_symbol_record)
5313                   + lst.hash_size * 4 
5314                   + lst.module_count * sizeof (struct som_entry)
5315                   + sizeof (struct lst_header);
5316             }
5317
5318           /* Keep track of the last symbol we added to this chain so we can
5319              easily update its next_entry pointer.  */
5320           last_hash_entry[curr_lst_sym->symbol_key % lst.hash_size]
5321             = curr_lst_sym;
5322
5323
5324           /* Update the string table.  */
5325           bfd_put_32 (abfd, strlen (sym->symbol.name), p);
5326           p += 4;
5327           strcpy (p, sym->symbol.name);
5328           p += strlen (sym->symbol.name) + 1;
5329           while ((int)p % 4)
5330             {
5331               bfd_put_8 (abfd, 0, p);
5332               p++;
5333             }
5334
5335           /* Head to the next symbol.  */
5336           curr_lst_sym++;
5337         }
5338
5339       /* Keep track of where each SOM will finally reside; then look
5340          at the next BFD.  */
5341       curr_som_offset += arelt_size (curr_bfd) + sizeof (struct ar_hdr);
5342       curr_bfd = curr_bfd->next;
5343       som_index++;
5344     }
5345
5346   /* Now scribble out the hash table.  */
5347   if (bfd_write ((PTR) hash_table, lst.hash_size, 4, abfd)
5348       != lst.hash_size * 4)
5349     goto error_return;
5350
5351   /* Then the SOM dictionary.  */
5352   if (bfd_write ((PTR) som_dict, lst.module_count,
5353                  sizeof (struct som_entry), abfd)
5354       != lst.module_count * sizeof (struct som_entry))
5355     goto error_return;
5356
5357   /* The library symbols.  */
5358   if (bfd_write ((PTR) lst_syms, nsyms, sizeof (struct lst_symbol_record), abfd)
5359       != nsyms * sizeof (struct lst_symbol_record))
5360     goto error_return;
5361
5362   /* And finally the strings.  */
5363   if (bfd_write ((PTR) strings, string_size, 1, abfd) != string_size)
5364     goto error_return;
5365
5366   if (hash_table != NULL)
5367     free (hash_table);
5368   if (som_dict != NULL)
5369     free (som_dict);
5370   if (last_hash_entry != NULL)
5371     free (last_hash_entry);
5372   if (lst_syms != NULL)
5373     free (lst_syms);
5374   if (strings != NULL)
5375     free (strings);
5376   return true;
5377
5378  error_return:
5379   if (hash_table != NULL)
5380     free (hash_table);
5381   if (som_dict != NULL)
5382     free (som_dict);
5383   if (last_hash_entry != NULL)
5384     free (last_hash_entry);
5385   if (lst_syms != NULL)
5386     free (lst_syms);
5387   if (strings != NULL)
5388     free (strings);
5389
5390   return false;
5391 }
5392
5393 /* Write out the LST for the archive.
5394
5395    You'll never believe this is really how armaps are handled in SOM...  */
5396
5397 /*ARGSUSED*/
5398 static boolean
5399 som_write_armap (abfd, elength, map, orl_count, stridx)
5400      bfd *abfd;
5401      unsigned int elength;
5402      struct orl *map;
5403      unsigned int orl_count;
5404      int stridx;
5405 {
5406   bfd *curr_bfd;
5407   struct stat statbuf;
5408   unsigned int i, lst_size, nsyms, stringsize;
5409   struct ar_hdr hdr;
5410   struct lst_header lst;
5411   int *p;
5412  
5413   /* We'll use this for the archive's date and mode later.  */
5414   if (stat (abfd->filename, &statbuf) != 0)
5415     {
5416       bfd_set_error (bfd_error_system_call);
5417       return false;
5418     }
5419   /* Fudge factor.  */
5420   bfd_ardata (abfd)->armap_timestamp = statbuf.st_mtime + 60;
5421
5422   /* Account for the lst header first.  */
5423   lst_size = sizeof (struct lst_header);
5424
5425   /* Start building the LST header.  */
5426   lst.system_id = CPU_PA_RISC1_0;
5427   lst.a_magic = LIBMAGIC;
5428   lst.version_id = VERSION_ID;
5429   lst.file_time.secs = 0;
5430   lst.file_time.nanosecs = 0;
5431
5432   lst.hash_loc = lst_size;
5433   lst.hash_size = SOM_LST_HASH_SIZE;
5434
5435   /* Hash table is a SOM_LST_HASH_SIZE 32bit offsets.  */
5436   lst_size += 4 * SOM_LST_HASH_SIZE;
5437
5438   /* We need to count the number of SOMs in this archive.  */
5439   curr_bfd = abfd->archive_head;
5440   lst.module_count = 0;
5441   while (curr_bfd != NULL)
5442     {
5443       /* Only true SOM objects count.  */
5444       if (curr_bfd->format == bfd_object
5445           && curr_bfd->xvec->flavour == bfd_target_som_flavour)
5446         lst.module_count++;
5447       curr_bfd = curr_bfd->next;
5448     }
5449   lst.module_limit = lst.module_count;
5450   lst.dir_loc = lst_size;
5451   lst_size += sizeof (struct som_entry) * lst.module_count;
5452
5453   /* We don't support import/export tables, auxiliary headers,
5454      or free lists yet.  Make the linker work a little harder
5455      to make our life easier.  */
5456
5457   lst.export_loc = 0;
5458   lst.export_count = 0;
5459   lst.import_loc = 0;
5460   lst.aux_loc = 0;
5461   lst.aux_size = 0;
5462
5463   /* Count how many symbols we will have on the hash chains and the
5464      size of the associated string table.  */
5465   if (som_bfd_prep_for_ar_write (abfd, &nsyms, &stringsize) == false)
5466     return false;
5467
5468   lst_size += sizeof (struct lst_symbol_record) * nsyms;
5469
5470   /* For the string table.  One day we might actually use this info
5471      to avoid small seeks/reads when reading archives.  */
5472   lst.string_loc = lst_size;
5473   lst.string_size = stringsize;
5474   lst_size += stringsize;
5475
5476   /* SOM ABI says this must be zero.  */
5477   lst.free_list = 0;
5478   lst.file_end = lst_size;
5479
5480   /* Compute the checksum.  Must happen after the entire lst header
5481      has filled in.  */
5482   p = (int *)&lst;
5483   lst.checksum = 0;
5484   for (i = 0; i < sizeof (struct lst_header)/sizeof (int) - 1; i++)
5485     lst.checksum ^= *p++;
5486
5487   sprintf (hdr.ar_name, "/               ");
5488   sprintf (hdr.ar_date, "%ld", bfd_ardata (abfd)->armap_timestamp);
5489   sprintf (hdr.ar_uid, "%ld", (long) getuid ());
5490   sprintf (hdr.ar_gid, "%ld", (long) getgid ());
5491   sprintf (hdr.ar_mode, "%-8o", (unsigned int) statbuf.st_mode);
5492   sprintf (hdr.ar_size, "%-10d", (int) lst_size);
5493   hdr.ar_fmag[0] = '`';
5494   hdr.ar_fmag[1] = '\012';
5495
5496   /* Turn any nulls into spaces.  */
5497   for (i = 0; i < sizeof (struct ar_hdr); i++)
5498     if (((char *) (&hdr))[i] == '\0')
5499       (((char *) (&hdr))[i]) = ' ';
5500
5501   /* Scribble out the ar header.  */
5502   if (bfd_write ((PTR) &hdr, 1, sizeof (struct ar_hdr), abfd)
5503       != sizeof (struct ar_hdr))
5504     return false;
5505
5506   /* Now scribble out the lst header.  */
5507   if (bfd_write ((PTR) &lst, 1, sizeof (struct lst_header), abfd)
5508       != sizeof (struct lst_header))
5509     return false;
5510
5511   /* Build and write the armap.  */
5512   if (som_bfd_ar_write_symbol_stuff (abfd, nsyms, stringsize, lst) == false)
5513     return false;
5514   
5515   /* Done.  */
5516   return true;
5517 }
5518
5519 /* Free all information we have cached for this BFD.  We can always
5520    read it again later if we need it.  */
5521
5522 static boolean
5523 som_bfd_free_cached_info (abfd)
5524      bfd *abfd;
5525 {
5526   asection *o;
5527
5528   if (bfd_get_format (abfd) != bfd_object)
5529     return true;
5530
5531 #define FREE(x) if (x != NULL) { free (x); x = NULL; }
5532   /* Free the native string and symbol tables.  */
5533   FREE (obj_som_symtab (abfd));
5534   FREE (obj_som_stringtab (abfd));
5535   for (o = abfd->sections; o != (asection *) NULL; o = o->next)
5536     {
5537       /* Free the native relocations.  */
5538       o->reloc_count = -1;
5539       FREE (som_section_data (o)->reloc_stream);
5540       /* Free the generic relocations.  */
5541       FREE (o->relocation);
5542     }
5543 #undef FREE
5544
5545   return true;
5546 }
5547
5548 /* End of miscellaneous support functions. */
5549
5550 #define som_close_and_cleanup           som_bfd_free_cached_info
5551
5552 #define som_openr_next_archived_file    bfd_generic_openr_next_archived_file
5553 #define som_generic_stat_arch_elt       bfd_generic_stat_arch_elt
5554 #define som_truncate_arname             bfd_bsd_truncate_arname
5555 #define som_slurp_extended_name_table   _bfd_slurp_extended_name_table
5556 #define som_update_armap_timestamp      bfd_true
5557
5558 #define som_get_lineno                  _bfd_nosymbols_get_lineno
5559 #define som_bfd_make_debug_symbol       _bfd_nosymbols_bfd_make_debug_symbol
5560
5561 #define som_bfd_get_relocated_section_contents \
5562  bfd_generic_get_relocated_section_contents
5563 #define som_bfd_relax_section bfd_generic_relax_section
5564 #define som_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
5565 #define som_bfd_link_add_symbols _bfd_generic_link_add_symbols
5566 #define som_bfd_final_link _bfd_generic_final_link
5567
5568 const bfd_target som_vec =
5569 {
5570   "som",                        /* name */
5571   bfd_target_som_flavour,
5572   true,                         /* target byte order */
5573   true,                         /* target headers byte order */
5574   (HAS_RELOC | EXEC_P |         /* object flags */
5575    HAS_LINENO | HAS_DEBUG |
5576    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED | DYNAMIC),
5577   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
5578    | SEC_ALLOC | SEC_LOAD | SEC_RELOC),         /* section flags */
5579
5580 /* leading_symbol_char: is the first char of a user symbol
5581    predictable, and if so what is it */
5582   0,
5583   '/',                          /* ar_pad_char */
5584   14,                           /* ar_max_namelen */
5585   3,                            /* minimum alignment */
5586   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
5587   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
5588   bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* data */
5589   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
5590   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
5591   bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* hdrs */
5592   {_bfd_dummy_target,
5593    som_object_p,                /* bfd_check_format */
5594    bfd_generic_archive_p,
5595    _bfd_dummy_target
5596   },
5597   {
5598     bfd_false,
5599     som_mkobject,
5600     _bfd_generic_mkarchive,
5601     bfd_false
5602   },
5603   {
5604     bfd_false,
5605     som_write_object_contents,
5606     _bfd_write_archive_contents,
5607     bfd_false,
5608   },
5609 #undef som
5610
5611   BFD_JUMP_TABLE_GENERIC (som),
5612   BFD_JUMP_TABLE_COPY (som),
5613   BFD_JUMP_TABLE_CORE (_bfd_nocore),
5614   BFD_JUMP_TABLE_ARCHIVE (som),
5615   BFD_JUMP_TABLE_SYMBOLS (som),
5616   BFD_JUMP_TABLE_RELOCS (som),
5617   BFD_JUMP_TABLE_WRITE (som),
5618   BFD_JUMP_TABLE_LINK (som),
5619   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
5620
5621   (PTR) 0
5622 };
5623
5624 #endif /* HOST_HPPAHPUX || HOST_HPPABSD || HOST_HPPAOSF */