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