433278cd8828d1d2bb2687262489d63af834be17
[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 one or more appropriate SOM relocations.  */
1366
1367 int **
1368 hppa_som_gen_reloc_type (abfd, base_type, format, field)
1369      bfd *abfd;
1370      int base_type;
1371      int format;
1372      enum hppa_reloc_field_selector_type field;
1373 {
1374   int *final_type, **final_types;
1375
1376   final_types = (int **) bfd_alloc_by_size_t (abfd, sizeof (int *) * 3);
1377   final_type = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
1378   if (!final_types || !final_type)
1379     {
1380       bfd_error = no_memory;
1381       return NULL;
1382     }
1383
1384   /* The field selector may require additional relocations to be 
1385      generated.  It's impossible to know at this moment if additional
1386      relocations will be needed, so we make them.  The code to actually
1387      write the relocation/fixup stream is responsible for removing
1388      any redundant relocations.  */
1389   switch (field)
1390     {
1391       case e_fsel:
1392       case e_psel:
1393       case e_lpsel:
1394       case e_rpsel:
1395         final_types[0] = final_type;
1396         final_types[1] = NULL;
1397         final_types[2] = NULL;
1398         *final_type = base_type;
1399         break;
1400
1401       case e_tsel:
1402       case e_ltsel:
1403       case e_rtsel:
1404         final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
1405         if (!final_types[0])
1406           {
1407             bfd_error = no_memory;
1408             return NULL;
1409           }
1410         if (field == e_tsel)
1411           *final_types[0] = R_FSEL;
1412         else if (field == e_ltsel)
1413           *final_types[0] = R_LSEL;
1414         else
1415           *final_types[0] = R_RSEL;
1416         final_types[1] = final_type;
1417         final_types[2] = NULL;
1418         *final_type = base_type;
1419         break;
1420
1421       case e_lssel:
1422       case e_rssel:
1423         final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
1424         if (!final_types[0])
1425           {
1426             bfd_error = no_memory;
1427             return NULL;
1428           }
1429         *final_types[0] = R_S_MODE;
1430         final_types[1] = final_type;
1431         final_types[2] = NULL;
1432         *final_type = base_type;
1433         break;
1434
1435       case e_lsel:
1436       case e_rsel:
1437         final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
1438         if (!final_types[0])
1439           {
1440             bfd_error = no_memory;
1441             return NULL;
1442           }
1443         *final_types[0] = R_N_MODE;
1444         final_types[1] = final_type;
1445         final_types[2] = NULL;
1446         *final_type = base_type;
1447         break;
1448
1449       case e_ldsel:
1450       case e_rdsel:
1451         final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
1452         if (!final_types[0])
1453           {
1454             bfd_error = no_memory;
1455             return NULL;
1456           }
1457         *final_types[0] = R_D_MODE;
1458         final_types[1] = final_type;
1459         final_types[2] = NULL;
1460         *final_type = base_type;
1461         break;
1462
1463       case e_lrsel:
1464       case e_rrsel:
1465         final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
1466         if (!final_types[0])
1467           {
1468             bfd_error = no_memory;
1469             return NULL;
1470           }
1471         *final_types[0] = R_R_MODE;
1472         final_types[1] = final_type;
1473         final_types[2] = NULL;
1474         *final_type = base_type;
1475         break;
1476     }
1477   
1478   switch (base_type)
1479     {
1480     case R_HPPA:
1481       /* PLABELs get their own relocation type.  */
1482       if (field == e_psel
1483           || field == e_lpsel
1484           || field == e_rpsel)
1485         {
1486           /* A PLABEL relocation that has a size of 32 bits must
1487              be a R_DATA_PLABEL.  All others are R_CODE_PLABELs.  */
1488           if (format == 32)
1489             *final_type = R_DATA_PLABEL;
1490           else
1491             *final_type = R_CODE_PLABEL;
1492         }
1493       /* PIC stuff.  */
1494       else if (field == e_tsel
1495           || field == e_ltsel
1496           || field == e_rtsel)
1497         *final_type = R_DLT_REL;
1498       /* A relocation in the data space is always a full 32bits.  */
1499       else if (format == 32)
1500         *final_type = R_DATA_ONE_SYMBOL;
1501
1502       break;
1503
1504     case R_HPPA_GOTOFF:
1505       /* More PLABEL special cases.  */
1506       if (field == e_psel
1507           || field == e_lpsel
1508           || field == e_rpsel)
1509         *final_type = R_DATA_PLABEL;
1510       break;
1511
1512     case R_HPPA_NONE:
1513     case R_HPPA_ABS_CALL:
1514     case R_HPPA_PCREL_CALL:
1515     case R_HPPA_COMPLEX:
1516     case R_HPPA_COMPLEX_PCREL_CALL:
1517     case R_HPPA_COMPLEX_ABS_CALL:
1518       /* Right now we can default all these.  */
1519       break;
1520     }
1521   return final_types;
1522 }
1523
1524 /* Return the address of the correct entry in the PA SOM relocation
1525    howto table.  */
1526
1527 static const reloc_howto_type *
1528 som_bfd_reloc_type_lookup (arch, code)
1529      bfd_arch_info_type *arch;
1530      bfd_reloc_code_real_type code;
1531 {
1532   if ((int) code < (int) R_NO_RELOCATION + 255)
1533     {
1534       BFD_ASSERT ((int) som_hppa_howto_table[(int) code].type == (int) code);
1535       return &som_hppa_howto_table[(int) code];
1536     }
1537
1538   return (reloc_howto_type *) 0;
1539 }
1540
1541 /* Perform some initialization for an object.  Save results of this
1542    initialization in the BFD.  */
1543
1544 static bfd_target *
1545 som_object_setup (abfd, file_hdrp, aux_hdrp)
1546      bfd *abfd;
1547      struct header *file_hdrp;
1548      struct som_exec_auxhdr *aux_hdrp;
1549 {
1550   /* som_mkobject will set bfd_error if som_mkobject fails.  */
1551   if (som_mkobject (abfd) != true)
1552     return 0;
1553
1554   /* Set BFD flags based on what information is available in the SOM.  */
1555   abfd->flags = NO_FLAGS;
1556   if (! file_hdrp->entry_offset)
1557     abfd->flags |= HAS_RELOC;
1558   else
1559     abfd->flags |= EXEC_P;
1560   if (file_hdrp->symbol_total)
1561     abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
1562
1563   bfd_get_start_address (abfd) = aux_hdrp->exec_entry;
1564   bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 0);
1565   bfd_get_symcount (abfd) = file_hdrp->symbol_total;
1566
1567   /* Initialize the saved symbol table and string table to NULL.  
1568      Save important offsets and sizes from the SOM header into
1569      the BFD.  */
1570   obj_som_stringtab (abfd) = (char  *) NULL;
1571   obj_som_symtab (abfd) = (som_symbol_type *) NULL;
1572   obj_som_stringtab_size (abfd) = file_hdrp->symbol_strings_size;
1573   obj_som_sym_filepos (abfd) = file_hdrp->symbol_location;
1574   obj_som_str_filepos (abfd) = file_hdrp->symbol_strings_location;
1575   obj_som_reloc_filepos (abfd) = file_hdrp->fixup_request_location;
1576
1577   return abfd->xvec;
1578 }
1579
1580 /* Create a new BFD section for NAME.  If NAME already exists, then create a
1581    new unique name, with NAME as the prefix.  This exists because SOM .o files
1582    may have more than one $CODE$ subspace.  */
1583
1584 static asection *
1585 make_unique_section (abfd, name, num)
1586      bfd *abfd;
1587      CONST char *name;
1588      int num;
1589 {
1590   asection *sect;
1591   char *newname;
1592   char altname[100];
1593
1594   sect = bfd_make_section (abfd, name);
1595   while (!sect)
1596     {
1597       sprintf (altname, "%s-%d", name, num++);
1598       sect = bfd_make_section (abfd, altname);
1599     }
1600
1601   newname = bfd_alloc (abfd, strlen (sect->name) + 1);
1602   if (!newname)
1603     {
1604       bfd_error = no_memory;
1605       return NULL;
1606     }
1607   strcpy (newname, sect->name);
1608
1609   sect->name = newname;
1610   return sect;
1611 }
1612
1613 /* Convert all of the space and subspace info into BFD sections.  Each space
1614    contains a number of subspaces, which in turn describe the mapping between
1615    regions of the exec file, and the address space that the program runs in.
1616    BFD sections which correspond to spaces will overlap the sections for the
1617    associated subspaces.  */
1618
1619 static boolean
1620 setup_sections (abfd, file_hdr)
1621      bfd *abfd;
1622      struct header *file_hdr;
1623 {
1624   char *space_strings;
1625   int space_index;
1626   unsigned int total_subspaces = 0;
1627
1628   /* First, read in space names */
1629
1630   space_strings = alloca (file_hdr->space_strings_size);
1631   if (!space_strings)
1632     return false;
1633
1634   if (bfd_seek (abfd, file_hdr->space_strings_location, SEEK_SET) < 0)
1635     return false;
1636   if (bfd_read (space_strings, 1, file_hdr->space_strings_size, abfd)
1637       != file_hdr->space_strings_size)
1638     return false;
1639
1640   /* Loop over all of the space dictionaries, building up sections */
1641   for (space_index = 0; space_index < file_hdr->space_total; space_index++)
1642     {
1643       struct space_dictionary_record space;
1644       struct subspace_dictionary_record subspace, save_subspace;
1645       int subspace_index;
1646       asection *space_asect;
1647
1648       /* Read the space dictionary element */
1649       if (bfd_seek (abfd, file_hdr->space_location
1650                     + space_index * sizeof space, SEEK_SET) < 0)
1651         return false;
1652       if (bfd_read (&space, 1, sizeof space, abfd) != sizeof space)
1653         return false;
1654
1655       /* Setup the space name string */
1656       space.name.n_name = space.name.n_strx + space_strings;
1657
1658       /* Make a section out of it */
1659       space_asect = make_unique_section (abfd, space.name.n_name, space_index);
1660       if (!space_asect)
1661         return false;
1662
1663       /* Now, read in the first subspace for this space */
1664       if (bfd_seek (abfd, file_hdr->subspace_location
1665                     + space.subspace_index * sizeof subspace,
1666                     SEEK_SET) < 0)
1667         return false;
1668       if (bfd_read (&subspace, 1, sizeof subspace, abfd) != sizeof subspace)
1669         return false;
1670       /* Seek back to the start of the subspaces for loop below */
1671       if (bfd_seek (abfd, file_hdr->subspace_location
1672                     + space.subspace_index * sizeof subspace,
1673                     SEEK_SET) < 0)
1674         return false;
1675
1676       /* Setup the start address and file loc from the first subspace record */
1677       space_asect->vma = subspace.subspace_start;
1678       space_asect->filepos = subspace.file_loc_init_value;
1679       space_asect->alignment_power = log2 (subspace.alignment);
1680
1681       /* Initialize save_subspace so we can reliably determine if this
1682          loop placed any useful values into it.  */
1683       memset (&save_subspace, 0, sizeof (struct subspace_dictionary_record));
1684
1685       /* Loop over the rest of the subspaces, building up more sections */
1686       for (subspace_index = 0; subspace_index < space.subspace_quantity;
1687            subspace_index++)
1688         {
1689           asection *subspace_asect;
1690
1691           /* Read in the next subspace */
1692           if (bfd_read (&subspace, 1, sizeof subspace, abfd)
1693               != sizeof subspace)
1694             return false;
1695
1696           /* Setup the subspace name string */
1697           subspace.name.n_name = subspace.name.n_strx + space_strings;
1698
1699           /* Make a section out of this subspace */
1700           subspace_asect = make_unique_section (abfd, subspace.name.n_name,
1701                                      space.subspace_index + subspace_index);
1702
1703           if (!subspace_asect)
1704             return false;
1705
1706           /* Keep an easy mapping between subspaces and sections.  */
1707           som_section_data (subspace_asect)->subspace_index 
1708             = total_subspaces++;
1709
1710           /* Set SEC_READONLY and SEC_CODE/SEC_DATA as specified
1711              by the access_control_bits in the subspace header.  */
1712           switch (subspace.access_control_bits >> 4)
1713             {
1714             /* Readonly data.  */  
1715             case 0x0:
1716               subspace_asect->flags |= SEC_DATA | SEC_READONLY;
1717               break;
1718
1719             /* Normal data.  */  
1720             case 0x1:
1721               subspace_asect->flags |= SEC_DATA;
1722               break;
1723
1724             /* Readonly code and the gateways.
1725                Gateways have other attributes which do not map
1726                into anything BFD knows about.  */
1727             case 0x2:
1728             case 0x4:
1729             case 0x5:
1730             case 0x6:
1731             case 0x7:
1732               subspace_asect->flags |= SEC_CODE | SEC_READONLY;
1733               break;
1734
1735             /* dynamic (writable) code.  */
1736             case 0x3:
1737               subspace_asect->flags |= SEC_CODE;
1738               break;
1739             }
1740           
1741           if (subspace.dup_common || subspace.is_common) 
1742             subspace_asect->flags |= SEC_IS_COMMON;
1743           else if (subspace.subspace_length > 0)
1744             subspace_asect->flags |= SEC_HAS_CONTENTS;
1745           if (subspace.is_loadable)
1746             subspace_asect->flags |= SEC_ALLOC | SEC_LOAD;
1747           if (subspace.code_only)
1748             subspace_asect->flags |= SEC_CODE;
1749
1750           /* Both file_loc_init_value and initialization_length will
1751              be zero for a BSS like subspace.  */
1752           if (subspace.file_loc_init_value == 0
1753               && subspace.initialization_length == 0)
1754             subspace_asect->flags &= ~(SEC_DATA | SEC_LOAD);
1755
1756           /* This subspace has relocations.
1757              The fixup_request_quantity is a byte count for the number of
1758              entries in the relocation stream; it is not the actual number
1759              of relocations in the subspace.  */
1760           if (subspace.fixup_request_quantity != 0)
1761             {
1762               subspace_asect->flags |= SEC_RELOC;
1763               subspace_asect->rel_filepos = subspace.fixup_request_index;
1764               som_section_data (subspace_asect)->reloc_size
1765                 = subspace.fixup_request_quantity;
1766               /* We can not determine this yet.  When we read in the 
1767                  relocation table the correct value will be filled in.  */
1768               subspace_asect->reloc_count = -1;
1769             }
1770
1771           /* Update save_subspace if appropriate.  */
1772           if (subspace.file_loc_init_value > save_subspace.file_loc_init_value)
1773             save_subspace = subspace;
1774
1775           subspace_asect->vma = subspace.subspace_start;
1776           subspace_asect->_cooked_size = subspace.subspace_length;
1777           subspace_asect->_raw_size = subspace.subspace_length;
1778           subspace_asect->alignment_power = log2 (subspace.alignment);
1779           subspace_asect->filepos = subspace.file_loc_init_value;
1780         }
1781
1782       /* Yow! there is no subspace within the space which actually 
1783          has initialized information in it; this should never happen
1784          as far as I know.  */
1785       if (!save_subspace.file_loc_init_value)
1786         abort ();
1787
1788       /* Setup the sizes for the space section based upon the info in the
1789          last subspace of the space.  */
1790       space_asect->_cooked_size = save_subspace.subspace_start
1791         - space_asect->vma + save_subspace.subspace_length;
1792       space_asect->_raw_size = save_subspace.file_loc_init_value
1793         - space_asect->filepos + save_subspace.initialization_length;
1794     }
1795   return true;
1796 }
1797
1798 /* Read in a SOM object and make it into a BFD.  */
1799
1800 static bfd_target *
1801 som_object_p (abfd)
1802      bfd *abfd;
1803 {
1804   struct header file_hdr;
1805   struct som_exec_auxhdr aux_hdr;
1806
1807   if (bfd_read ((PTR) & file_hdr, 1, FILE_HDR_SIZE, abfd) != FILE_HDR_SIZE)
1808     {
1809       bfd_error = system_call_error;
1810       return 0;
1811     }
1812
1813   if (!_PA_RISC_ID (file_hdr.system_id))
1814     {
1815       bfd_error = wrong_format;
1816       return 0;
1817     }
1818
1819   switch (file_hdr.a_magic)
1820     {
1821     case RELOC_MAGIC:
1822     case EXEC_MAGIC:
1823     case SHARE_MAGIC:
1824     case DEMAND_MAGIC:
1825 #ifdef DL_MAGIC
1826     case DL_MAGIC:
1827 #endif
1828 #ifdef SHL_MAGIC
1829     case SHL_MAGIC:
1830 #endif
1831 #ifdef EXECLIBMAGIC
1832     case EXECLIBMAGIC:
1833 #endif
1834 #ifdef SHARED_MAGIC_CNX
1835     case SHARED_MAGIC_CNX:
1836 #endif
1837       break;
1838     default:
1839       bfd_error = wrong_format;
1840       return 0;
1841     }
1842
1843   if (file_hdr.version_id != VERSION_ID
1844       && file_hdr.version_id != NEW_VERSION_ID)
1845     {
1846       bfd_error = wrong_format;
1847       return 0;
1848     }
1849
1850   /* If the aux_header_size field in the file header is zero, then this
1851      object is an incomplete executable (a .o file).  Do not try to read
1852      a non-existant auxiliary header.  */
1853   memset (&aux_hdr, 0, sizeof (struct som_exec_auxhdr));
1854   if (file_hdr.aux_header_size != 0)
1855     {
1856       if (bfd_read ((PTR) & aux_hdr, 1, AUX_HDR_SIZE, abfd) != AUX_HDR_SIZE)
1857         {
1858           bfd_error = wrong_format;
1859           return 0;
1860         }
1861     }
1862
1863   if (!setup_sections (abfd, &file_hdr))
1864     {
1865       /* setup_sections does not bubble up a bfd error code.  */
1866       bfd_error = bad_value;
1867       return 0;
1868     }
1869
1870   /* This appears to be a valid SOM object.  Do some initialization.  */
1871   return som_object_setup (abfd, &file_hdr, &aux_hdr);
1872 }
1873
1874 /* Create a SOM object.  */
1875
1876 static boolean
1877 som_mkobject (abfd)
1878      bfd *abfd;
1879 {
1880   /* Allocate memory to hold backend information.  */
1881   abfd->tdata.som_data = (struct som_data_struct *)
1882     bfd_zalloc (abfd, sizeof (struct som_data_struct));
1883   if (abfd->tdata.som_data == NULL)
1884     {
1885       bfd_error = no_memory;
1886       return false;
1887     }
1888   obj_som_file_hdr (abfd)
1889     = (struct header *) bfd_zalloc (abfd, sizeof (struct header));
1890   if (obj_som_file_hdr (abfd) == NULL)
1891
1892     {
1893       bfd_error = no_memory;
1894       return false;
1895     }
1896   return true;
1897 }
1898
1899 /* Initialize some information in the file header.  This routine makes
1900    not attempt at doing the right thing for a full executable; it
1901    is only meant to handle relocatable objects.  */
1902
1903 static boolean
1904 som_prep_headers (abfd)
1905      bfd *abfd;
1906 {
1907   struct header *file_hdr = obj_som_file_hdr (abfd);
1908   asection *section;
1909
1910   /* FIXME.  This should really be conditional based on whether or not
1911      PA1.1 instructions/registers have been used.  */
1912   file_hdr->system_id = HP9000S800_ID;
1913
1914   /* FIXME.  Only correct for building relocatable objects.  */
1915   if (abfd->flags & EXEC_P)
1916     abort ();
1917   else
1918     file_hdr->a_magic = RELOC_MAGIC;
1919
1920   /* Only new format SOM is supported.  */
1921   file_hdr->version_id = NEW_VERSION_ID;
1922
1923   /* These fields are optional, and embedding timestamps is not always
1924      a wise thing to do, it makes comparing objects during a multi-stage
1925      bootstrap difficult.  */
1926   file_hdr->file_time.secs = 0;
1927   file_hdr->file_time.nanosecs = 0; 
1928
1929   if (abfd->flags & EXEC_P)
1930     abort ();
1931   else
1932     {
1933       file_hdr->entry_space = 0;
1934       file_hdr->entry_subspace = 0;
1935       file_hdr->entry_offset = 0;
1936     }
1937   
1938   file_hdr->presumed_dp = 0;
1939
1940   /* Now iterate over the sections translating information from
1941      BFD sections to SOM spaces/subspaces.  */
1942
1943   for (section = abfd->sections; section != NULL; section = section->next)
1944     {
1945       /* Ignore anything which has not been marked as a space or
1946          subspace.  */
1947       if (som_section_data (section)->is_space == 0
1948
1949           && som_section_data (section)->is_subspace == 0)
1950         continue;
1951
1952       if (som_section_data (section)->is_space)
1953         {
1954           /* Set space attributes.  Note most attributes of SOM spaces
1955              are set based on the subspaces it contains.  */
1956           som_section_data (section)->space_dict.loader_fix_index = -1;
1957           som_section_data (section)->space_dict.init_pointer_index = -1;
1958         }
1959       else
1960         {
1961           /* Set subspace attributes.  Basic stuff is done here, additional
1962              attributes are filled in later as more information becomes
1963              available.  */
1964           if (section->flags & SEC_IS_COMMON)
1965             {
1966               som_section_data (section)->subspace_dict.dup_common = 1;
1967               som_section_data (section)->subspace_dict.is_common = 1;
1968             }
1969
1970           if (section->flags & SEC_ALLOC)
1971             som_section_data (section)->subspace_dict.is_loadable = 1;
1972
1973           if (section->flags & SEC_CODE)
1974             som_section_data (section)->subspace_dict.code_only = 1;
1975
1976           som_section_data (section)->subspace_dict.subspace_start = 
1977             section->vma;
1978           som_section_data (section)->subspace_dict.subspace_length =
1979             bfd_section_size (abfd, section);
1980           som_section_data (section)->subspace_dict.initialization_length =
1981             bfd_section_size (abfd, section);
1982           som_section_data (section)->subspace_dict.alignment = 
1983             1 << section->alignment_power;
1984         }
1985     }
1986   return true;
1987 }
1988
1989 /* Count and return the number of spaces attached to the given BFD.  */
1990
1991 static unsigned long
1992 som_count_spaces (abfd)
1993      bfd *abfd;
1994 {
1995   int count = 0;
1996   asection *section;
1997
1998   for (section = abfd->sections; section != NULL; section = section->next)
1999     count += som_section_data (section)->is_space;
2000
2001   return count;
2002 }
2003
2004 /* Count the number of subspaces attached to the given BFD.  */
2005
2006 static unsigned long
2007 som_count_subspaces (abfd)
2008      bfd *abfd;
2009 {
2010   int count = 0;
2011   asection *section;
2012
2013   for (section = abfd->sections; section != NULL; section = section->next)
2014     count += som_section_data (section)->is_subspace;
2015
2016   return count;
2017 }
2018
2019 /* Return -1, 0, 1 indicating the relative ordering of sym1 and sym2.
2020
2021    We desire symbols to be ordered starting with the symbol with the
2022    highest relocation count down to the symbol with the lowest relocation
2023    count.  Doing so compacts the relocation stream.  */
2024
2025 static int
2026 compare_syms (sym1, sym2)
2027      asymbol **sym1;
2028      asymbol **sym2;
2029
2030 {
2031   unsigned int count1, count2;
2032   
2033   /* Get relocation count for each symbol.  Note that the count
2034      is stored in the udata pointer for section symbols!  */
2035   if ((*sym1)->flags & BSF_SECTION_SYM)
2036     count1 = (int)(*sym1)->udata;
2037   else
2038     count1 = som_symbol_data (*sym1)->reloc_count;
2039
2040   if ((*sym2)->flags & BSF_SECTION_SYM)
2041     count2 = (int)(*sym2)->udata;
2042   else
2043     count2 = som_symbol_data (*sym2)->reloc_count;
2044
2045   /* Return the appropriate value.  */
2046   if (count1 < count2)
2047     return 1;
2048   else if (count1 > count2)
2049     return -1;
2050   return 0;
2051 }
2052
2053 /* Perform various work in preparation for emitting the fixup stream.  */
2054
2055 static void
2056 som_prep_for_fixups (abfd, syms, num_syms)
2057      bfd *abfd;
2058      asymbol **syms;
2059      unsigned long num_syms;
2060 {
2061   int i;
2062   asection *section;
2063
2064   /* Most SOM relocations involving a symbol have a length which is
2065      dependent on the index of the symbol.  So symbols which are
2066      used often in relocations should have a small index.  */
2067
2068   /* First initialize the counters for each symbol.  */
2069   for (i = 0; i < num_syms; i++)
2070     {
2071       /* Handle a section symbol; these have no pointers back to the 
2072          SOM symbol info.  So we just use the pointer field (udata)
2073          to hold the relocation count.
2074
2075          FIXME.  While we're here set the name of any section symbol
2076          to something which will not screw GDB.  How do other formats
2077          deal with this?!?  */
2078       if (som_symbol_data (syms[i]) == NULL)
2079         {
2080           syms[i]->flags |= BSF_SECTION_SYM;
2081           syms[i]->name = "L$0\002";
2082           syms[i]->udata = (PTR) 0;
2083         }
2084       else
2085         som_symbol_data (syms[i])->reloc_count = 0;
2086     }
2087
2088   /* Now that the counters are initialized, make a weighted count
2089      of how often a given symbol is used in a relocation.  */
2090   for (section = abfd->sections; section != NULL; section = section->next)
2091     {
2092       int i;
2093
2094       /* Does this section have any relocations?  */
2095       if (section->reloc_count <= 0)
2096         continue;
2097
2098       /* Walk through each relocation for this section.  */
2099       for (i = 1; i < section->reloc_count; i++)
2100         {
2101           arelent *reloc = section->orelocation[i];
2102           int scale;
2103
2104           /* If no symbol, then there is no counter to increase.  */
2105           if (reloc->sym_ptr_ptr == NULL)
2106             continue;
2107
2108           /* Scaling to encourage symbols involved in R_DP_RELATIVE 
2109              and R_CODE_ONE_SYMBOL relocations to come first.  These
2110              two relocations have single byte versions if the symbol
2111              index is very small.  */
2112           if (reloc->howto->type == R_DP_RELATIVE
2113               || reloc->howto->type == R_CODE_ONE_SYMBOL)
2114             scale = 2;
2115           else
2116             scale = 1;
2117
2118           /* Handle section symbols by ramming the count in the udata
2119              field.  It will not be used and the count is very important
2120              for these symbols.  */
2121           if ((*reloc->sym_ptr_ptr)->flags & BSF_SECTION_SYM)
2122             {
2123               (*reloc->sym_ptr_ptr)->udata =
2124                 (PTR) ((int) (*reloc->sym_ptr_ptr)->udata + scale);
2125               continue;
2126             }
2127
2128           /* A normal symbol.  Increment the count.  */
2129           som_symbol_data (*reloc->sym_ptr_ptr)->reloc_count += scale;
2130         }
2131     }
2132
2133   /* Now sort the symbols.  */
2134   qsort (syms, num_syms, sizeof (asymbol *), compare_syms);
2135
2136   /* Compute the symbol indexes, they will be needed by the relocation
2137      code.  */
2138   for (i = 0; i < num_syms; i++)
2139     {
2140       /* A section symbol.  Again, there is no pointer to backend symbol
2141          information, so we reuse (abuse) the udata field again.  */
2142       if (syms[i]->flags & BSF_SECTION_SYM)
2143         syms[i]->udata = (PTR) i;
2144       else
2145         som_symbol_data (syms[i])->index = i;
2146     }
2147 }
2148
2149 static boolean
2150 som_write_fixups (abfd, current_offset, total_reloc_sizep)
2151      bfd *abfd;
2152      unsigned long current_offset;
2153      unsigned int *total_reloc_sizep;
2154 {
2155   unsigned int i, j;
2156   unsigned char *tmp_space, *p;
2157   unsigned int total_reloc_size = 0;
2158   unsigned int subspace_reloc_size = 0;
2159   unsigned int num_spaces = obj_som_file_hdr (abfd)->space_total;
2160   asection *section = abfd->sections;
2161
2162   /* Get a chunk of memory that we can use as buffer space, then throw
2163      away.  */
2164   tmp_space = alloca (SOM_TMP_BUFSIZE);
2165   memset (tmp_space, 0, SOM_TMP_BUFSIZE);
2166   p = tmp_space;
2167
2168   /* All the fixups for a particular subspace are emitted in a single
2169      stream.  All the subspaces for a particular space are emitted
2170      as a single stream.
2171
2172      So, to get all the locations correct one must iterate through all the
2173      spaces, for each space iterate through its subspaces and output a
2174      fixups stream.  */
2175   for (i = 0; i < num_spaces; i++)
2176     {
2177       asection *subsection;
2178
2179       /* Find a space.  */
2180       while (som_section_data (section)->is_space == 0)
2181         section = section->next;
2182
2183       /* Now iterate through each of its subspaces.  */
2184       for (subsection = abfd->sections;
2185            subsection != NULL;
2186            subsection = subsection->next)
2187         {
2188           int reloc_offset, current_rounding_mode;
2189
2190           /* Find a subspace of this space.  */
2191           if (som_section_data (subsection)->is_subspace == 0
2192               || som_section_data (subsection)->containing_space != section)
2193             continue;
2194
2195           /* If this subspace had no relocations, then we're finished 
2196              with it.  */
2197           if (subsection->reloc_count <= 0)
2198             {
2199               som_section_data (subsection)->subspace_dict.fixup_request_index
2200                 = -1;
2201               continue;
2202             }
2203
2204           /* This subspace has some relocations.  Put the relocation stream
2205              index into the subspace record.  */
2206           som_section_data (subsection)->subspace_dict.fixup_request_index
2207             = total_reloc_size;
2208
2209           /* To make life easier start over with a clean slate for 
2210              each subspace.  Seek to the start of the relocation stream
2211              for this subspace in preparation for writing out its fixup
2212              stream.  */
2213           if (bfd_seek (abfd, current_offset + total_reloc_size, SEEK_SET) != 0)
2214             {
2215               bfd_error = system_call_error;
2216               return false;
2217             }
2218
2219           /* Buffer space has already been allocated.  Just perform some
2220              initialization here.  */
2221           p = tmp_space;
2222           subspace_reloc_size = 0;
2223           reloc_offset = 0;
2224           som_initialize_reloc_queue (reloc_queue);
2225           current_rounding_mode = R_N_MODE;
2226
2227           /* Translate each BFD relocation into one or more SOM 
2228              relocations.  */
2229           for (j = 0; j < subsection->reloc_count; j++)
2230             {
2231               arelent *bfd_reloc = subsection->orelocation[j];
2232               unsigned int skip;
2233               int sym_num;
2234
2235               /* Get the symbol number.  Remember it's stored in a 
2236                  special place for section symbols.  */
2237               if ((*bfd_reloc->sym_ptr_ptr)->flags & BSF_SECTION_SYM)
2238                 sym_num = (int) (*bfd_reloc->sym_ptr_ptr)->udata;
2239               else
2240                 sym_num = som_symbol_data (*bfd_reloc->sym_ptr_ptr)->index;
2241               
2242               /* If there is not enough room for the next couple relocations,
2243                  then dump the current buffer contents now.  Also reinitialize
2244                  the relocation queue. 
2245
2246                  No single BFD relocation could ever translate into more
2247                  than 100 bytes of SOM relocations (20bytes is probably the
2248                  upper limit, but leave lots of space for growth).  */
2249               if (p - tmp_space + 100 > SOM_TMP_BUFSIZE)
2250                 {
2251                   if (bfd_write ((PTR) tmp_space, p - tmp_space, 1, abfd)
2252                       != p - tmp_space)
2253                     {
2254                       bfd_error = system_call_error;
2255                       return false;
2256                     }
2257                   p = tmp_space;
2258                   som_initialize_reloc_queue (reloc_queue);
2259                 }
2260
2261               /* Emit R_NO_RELOCATION fixups to map any bytes which were
2262                  skipped.  */
2263               skip = bfd_reloc->address - reloc_offset;
2264               p = som_reloc_skip (abfd, skip, p,
2265                                   &subspace_reloc_size, reloc_queue);
2266
2267               /* Update reloc_offset for the next iteration.
2268
2269                  Many relocations do not consume input bytes.  They
2270                  are markers, or set state necessary to perform some
2271                  later relocation.  */
2272               switch (bfd_reloc->howto->type)
2273                 {
2274                 /* This only needs to handle relocations that may be
2275                    made by hppa_som_gen_reloc.  */
2276                 case R_ENTRY:
2277                 case R_EXIT:
2278                 case R_N_MODE:
2279                 case R_S_MODE:
2280                 case R_D_MODE:
2281                 case R_R_MODE:
2282                 case R_FSEL:
2283                 case R_LSEL:
2284                 case R_RSEL:
2285                   reloc_offset = bfd_reloc->address;
2286                   break;
2287
2288                 default:
2289                   reloc_offset = bfd_reloc->address + 4;
2290                   break;
2291                 }
2292
2293               /* Now the actual relocation we care about.  */
2294               switch (bfd_reloc->howto->type)
2295                 {
2296                 case R_PCREL_CALL:
2297                 case R_ABS_CALL:
2298                   p = som_reloc_call (abfd, p, &subspace_reloc_size,
2299                                       bfd_reloc, sym_num, reloc_queue);
2300                   break;
2301
2302                 case R_CODE_ONE_SYMBOL:
2303                 case R_DP_RELATIVE:
2304                   /* Account for any addend.  */
2305                   if (bfd_reloc->addend)
2306                     p = som_reloc_addend (abfd, bfd_reloc->addend, p, 
2307                                           &subspace_reloc_size, reloc_queue);
2308
2309                   if (sym_num < 0x20)
2310                     {
2311                       bfd_put_8 (abfd, bfd_reloc->howto->type + sym_num, p);
2312                       subspace_reloc_size += 1;
2313                       p += 1;
2314                     }
2315                   else if (sym_num < 0x100)
2316                     {
2317                       bfd_put_8 (abfd, bfd_reloc->howto->type + 32, p);
2318                       bfd_put_8 (abfd, sym_num, p + 1);
2319                       p = try_prev_fixup (abfd, &subspace_reloc_size, p,
2320                                           2, reloc_queue);
2321                     }
2322                   else if (sym_num < 0x10000000)
2323                     {
2324                       bfd_put_8 (abfd, bfd_reloc->howto->type + 33, p);
2325                       bfd_put_8 (abfd, sym_num >> 16, p + 1);
2326                       bfd_put_16 (abfd, sym_num, p + 2); 
2327                       p = try_prev_fixup (abfd, &subspace_reloc_size,
2328                                           p, 4, reloc_queue);
2329                     }
2330                   else
2331                     abort ();
2332                   break;
2333
2334                 case R_DATA_ONE_SYMBOL:
2335                 case R_DATA_PLABEL:
2336                 case R_CODE_PLABEL:
2337                 case R_DLT_REL:
2338                   /* Account for any addend.  */
2339                   if (bfd_reloc->addend)
2340                     p = som_reloc_addend (abfd, bfd_reloc->addend, p, 
2341                                           &subspace_reloc_size, reloc_queue);
2342
2343                   if (sym_num < 0x100)
2344                     {
2345                       bfd_put_8 (abfd, bfd_reloc->howto->type, p);
2346                       bfd_put_8 (abfd, sym_num, p + 1);
2347                       p = try_prev_fixup (abfd, &subspace_reloc_size, p,
2348                                           2, reloc_queue);
2349                     }
2350                   else if (sym_num < 0x10000000)
2351                     {
2352                       bfd_put_8 (abfd, bfd_reloc->howto->type + 1, p);
2353                       bfd_put_8 (abfd, sym_num >> 16, p + 1);
2354                       bfd_put_16 (abfd, sym_num, p + 2); 
2355                       p = try_prev_fixup (abfd, &subspace_reloc_size,
2356                                           p, 4, reloc_queue);
2357                     }
2358                   else
2359                     abort ();
2360                   break;
2361
2362                 case R_ENTRY:
2363                   {
2364                     int *descp
2365                        = (int *) som_symbol_data (*bfd_reloc->sym_ptr_ptr)->unwind;
2366                     bfd_put_8 (abfd, R_ENTRY, p);
2367                     bfd_put_32 (abfd, descp[0], p + 1);
2368                     bfd_put_32 (abfd, descp[1], p + 5);
2369                     p = try_prev_fixup (abfd, &subspace_reloc_size,
2370                                         p, 9, reloc_queue);
2371                     break;
2372                   }
2373                   
2374                 case R_EXIT:
2375                   bfd_put_8 (abfd, R_EXIT, p);
2376                   subspace_reloc_size += 1;
2377                   p += 1;
2378                   break;
2379
2380                 case R_N_MODE:
2381                 case R_S_MODE:
2382                 case R_D_MODE:
2383                 case R_R_MODE:
2384                   /* If this relocation requests the current rounding
2385                      mode, then it is redundant.  */
2386                   if (bfd_reloc->howto->type != current_rounding_mode)
2387                     {
2388                       bfd_put_8 (abfd, bfd_reloc->howto->type, p);
2389                       subspace_reloc_size += 1;
2390                       p += 1;
2391                       current_rounding_mode = bfd_reloc->howto->type;
2392                     }
2393                   break;
2394
2395                 case R_FSEL:
2396                 case R_LSEL:
2397                 case R_RSEL:
2398                   bfd_put_8 (abfd, bfd_reloc->howto->type, p);
2399                   subspace_reloc_size += 1;
2400                   p += 1;
2401                   break;
2402
2403                 /* Put a "R_RESERVED" relocation in the stream if
2404                    we hit something we do not understand.  The linker
2405                    will complain loudly if this ever happens.  */
2406                 default:
2407                   bfd_put_8 (abfd, 0xff, p);
2408                   subspace_reloc_size += 1;
2409                   p += 1;
2410                   break;
2411                 }
2412             }
2413
2414           /* Last BFD relocation for a subspace has been processed.
2415              Map the rest of the subspace with R_NO_RELOCATION fixups.  */
2416           p = som_reloc_skip (abfd, bfd_section_size (abfd, subsection) 
2417                                       - reloc_offset,
2418                               p, &subspace_reloc_size, reloc_queue);
2419
2420           /* Scribble out the relocations.  */
2421           if (bfd_write ((PTR) tmp_space, p - tmp_space, 1, abfd)
2422               != p - tmp_space)
2423             {
2424               bfd_error = system_call_error;
2425               return false;
2426             }
2427           p = tmp_space;
2428
2429           total_reloc_size += subspace_reloc_size;
2430           som_section_data (subsection)->subspace_dict.fixup_request_quantity
2431             = subspace_reloc_size;
2432         }
2433       section = section->next;
2434     }
2435   *total_reloc_sizep = total_reloc_size;
2436   return true;
2437 }
2438
2439 /* Write out the space/subspace string table.  */
2440
2441 static boolean
2442 som_write_space_strings (abfd, current_offset, string_sizep)
2443      bfd *abfd;
2444      unsigned long current_offset;
2445      unsigned int *string_sizep;
2446 {
2447   unsigned char *tmp_space, *p;
2448   unsigned int strings_size = 0;
2449   asection *section;
2450
2451   /* Get a chunk of memory that we can use as buffer space, then throw
2452      away.  */
2453   tmp_space = alloca (SOM_TMP_BUFSIZE);
2454   memset (tmp_space, 0, SOM_TMP_BUFSIZE);
2455   p = tmp_space;
2456
2457   /* Seek to the start of the space strings in preparation for writing
2458      them out.  */
2459   if (bfd_seek (abfd, current_offset, SEEK_SET) != 0)
2460     {
2461       bfd_error = system_call_error;
2462       return false;
2463     }
2464
2465   /* Walk through all the spaces and subspaces (order is not important)
2466      building up and writing string table entries for their names.  */
2467   for (section = abfd->sections; section != NULL; section = section->next)
2468     {
2469       int length;
2470
2471       /* Only work with space/subspaces; avoid any other sections
2472          which might have been made (.text for example).  */
2473       if (som_section_data (section)->is_space == 0
2474           && som_section_data (section)->is_subspace == 0)
2475         continue;
2476
2477       /* Get the length of the space/subspace name.  */
2478       length = strlen (section->name);
2479
2480       /* If there is not enough room for the next entry, then dump the
2481          current buffer contents now.  Each entry will take 4 bytes to
2482          hold the string length + the string itself + null terminator.  */
2483       if (p - tmp_space + 5 + length > SOM_TMP_BUFSIZE)
2484         {
2485           if (bfd_write ((PTR) tmp_space, p - tmp_space, 1, abfd)
2486               != p - tmp_space) 
2487             {
2488               bfd_error = system_call_error;
2489               return false;
2490             }
2491           /* Reset to beginning of the buffer space.  */
2492           p = tmp_space;
2493         }
2494
2495       /* First element in a string table entry is the length of the
2496          string.  Alignment issues are already handled.  */
2497       bfd_put_32 (abfd, length, p);
2498       p += 4;
2499       strings_size += 4;
2500
2501       /* Record the index in the space/subspace records.  */
2502       if (som_section_data (section)->is_space)
2503         som_section_data (section)->space_dict.name.n_strx = strings_size;
2504       else
2505         som_section_data (section)->subspace_dict.name.n_strx = strings_size;
2506
2507       /* Next comes the string itself + a null terminator.  */
2508       strcpy (p, section->name);
2509       p += length + 1;
2510       strings_size += length + 1;
2511
2512       /* Always align up to the next word boundary.  */
2513       while (strings_size % 4)
2514         {
2515           bfd_put_8 (abfd, 0, p);
2516           p++;
2517           strings_size++;
2518         }
2519     }
2520
2521   /* Done with the space/subspace strings.  Write out any information
2522      contained in a partial block.  */
2523   if (bfd_write ((PTR) tmp_space, p - tmp_space, 1, abfd) != p - tmp_space)
2524     {
2525       bfd_error = system_call_error;
2526       return false;
2527     }
2528   *string_sizep = strings_size;
2529   return true;
2530 }
2531
2532 /* Write out the symbol string table.  */
2533
2534 static boolean
2535 som_write_symbol_strings (abfd, current_offset, syms, num_syms, string_sizep)
2536      bfd *abfd;
2537      unsigned long current_offset;
2538      asymbol **syms;
2539      unsigned int num_syms;
2540      unsigned int *string_sizep;
2541 {
2542   unsigned int i;
2543   unsigned char *tmp_space, *p;
2544   unsigned int strings_size = 0;
2545
2546   /* Get a chunk of memory that we can use as buffer space, then throw
2547      away.  */
2548   tmp_space = alloca (SOM_TMP_BUFSIZE);
2549   memset (tmp_space, 0, SOM_TMP_BUFSIZE);
2550   p = tmp_space;
2551
2552   /* Seek to the start of the space strings in preparation for writing
2553      them out.  */
2554   if (bfd_seek (abfd, current_offset, SEEK_SET) != 0)
2555     {
2556       bfd_error = system_call_error;
2557       return false;
2558     }
2559
2560   for (i = 0; i < num_syms; i++)
2561     {
2562       int length = strlen (syms[i]->name);
2563
2564       /* If there is not enough room for the next entry, then dump the
2565          current buffer contents now.  */
2566      if (p - tmp_space + 5 + length > SOM_TMP_BUFSIZE)
2567         {
2568           if (bfd_write ((PTR) tmp_space, p - tmp_space, 1, abfd)
2569               != p - tmp_space)
2570             {
2571               bfd_error = system_call_error;
2572               return false;
2573             }
2574           /* Reset to beginning of the buffer space.  */
2575           p = tmp_space;
2576         }
2577
2578       /* First element in a string table entry is the length of the
2579          string.  This must always be 4 byte aligned.  This is also
2580          an appropriate time to fill in the string index field in the
2581          symbol table entry.  */
2582       bfd_put_32 (abfd, length, p);
2583       strings_size += 4;
2584       p += 4;
2585
2586       /* Next comes the string itself + a null terminator.  */
2587       strcpy (p, syms[i]->name);
2588
2589       /* ACK.  FIXME.  */
2590       syms[i]->name = (char *)strings_size;
2591       p += length + 1;
2592       strings_size += length + 1;
2593
2594       /* Always align up to the next word boundary.  */
2595       while (strings_size % 4)
2596         {
2597           bfd_put_8 (abfd, 0, p);
2598           strings_size++;
2599           p++;
2600         }
2601     }
2602
2603   /* Scribble out any partial block.  */
2604   if (bfd_write ((PTR) tmp_space, p - tmp_space, 1, abfd) != p - tmp_space)
2605     {
2606       bfd_error = system_call_error;
2607       return false;
2608     }
2609
2610   *string_sizep = strings_size;
2611   return true;
2612 }
2613
2614 /* Compute variable information to be placed in the SOM headers, 
2615    space/subspace dictionaries, relocation streams, etc.  Begin
2616    writing parts of the object file.  */
2617
2618 static boolean 
2619 som_begin_writing (abfd)
2620      bfd *abfd;
2621 {
2622   unsigned long current_offset = 0;
2623   int strings_size = 0;
2624   unsigned int total_reloc_size = 0;
2625   unsigned long num_spaces, num_subspaces, num_syms, i;
2626   asection *section;
2627   asymbol **syms = bfd_get_outsymbols (abfd);
2628   unsigned int total_subspaces = 0;
2629
2630   /* The file header will always be first in an object file, 
2631      everything else can be in random locations.  To keep things
2632      "simple" BFD will lay out the object file in the manner suggested
2633      by the PRO ABI for PA-RISC Systems.  */
2634
2635   /* Before any output can really begin offsets for all the major
2636      portions of the object file must be computed.  So, starting
2637      with the initial file header compute (and sometimes write)
2638      each portion of the object file.  */
2639
2640   /* Make room for the file header, it's contents are not complete
2641      yet, so it can not be written at this time.  */
2642   current_offset += sizeof (struct header);  
2643
2644   /* Any auxiliary headers will follow the file header.  Right now
2645      we support only the copyright and version headers.  */
2646   obj_som_file_hdr (abfd)->aux_header_location = current_offset;
2647   obj_som_file_hdr (abfd)->aux_header_size = 0;
2648   if (obj_som_version_hdr (abfd) != NULL)
2649     {
2650       unsigned int len;
2651
2652       bfd_seek (abfd, current_offset, SEEK_SET);
2653
2654       /* Write the aux_id structure and the string length.  */
2655       len = sizeof (struct aux_id) + sizeof (unsigned int);
2656       obj_som_file_hdr (abfd)->aux_header_size += len;
2657       current_offset += len;
2658       if (bfd_write ((PTR) obj_som_version_hdr (abfd), len, 1, abfd) != len)
2659         {
2660           bfd_error = system_call_error;
2661           return false;
2662         }
2663
2664       /* Write the version string.  */
2665       len = obj_som_version_hdr (abfd)->header_id.length - sizeof (int);
2666       obj_som_file_hdr (abfd)->aux_header_size += len;
2667       current_offset += len;
2668       if (bfd_write ((PTR) obj_som_version_hdr (abfd)->user_string,
2669                      len, 1, abfd) != len)
2670         {
2671           bfd_error = system_call_error;
2672           return false;
2673         }
2674     }
2675
2676   if (obj_som_copyright_hdr (abfd) != NULL)
2677     {
2678       unsigned int len;
2679
2680       bfd_seek (abfd, current_offset, SEEK_SET);
2681
2682       /* Write the aux_id structure and the string length.  */
2683       len = sizeof (struct aux_id) + sizeof (unsigned int);
2684       obj_som_file_hdr (abfd)->aux_header_size += len;
2685       current_offset += len;
2686       if (bfd_write ((PTR) obj_som_copyright_hdr (abfd), len, 1, abfd) != len)
2687         {
2688           bfd_error = system_call_error;
2689           return false;
2690         }
2691
2692       /* Write the copyright string.  */
2693       len = obj_som_copyright_hdr (abfd)->header_id.length - sizeof (int);
2694       obj_som_file_hdr (abfd)->aux_header_size += len;
2695       current_offset += len;
2696       if (bfd_write ((PTR) obj_som_copyright_hdr (abfd)->copyright,
2697                      len, 1, abfd) != len)
2698         {
2699           bfd_error = system_call_error;
2700           return false;
2701         }
2702     }
2703
2704   /* Next comes the initialization pointers; we have no initialization
2705      pointers, so current offset does not change.  */
2706   obj_som_file_hdr (abfd)->init_array_location = current_offset;
2707   obj_som_file_hdr (abfd)->init_array_total = 0;
2708
2709   /* Next are the space records.  These are fixed length records.
2710
2711      Count the number of spaces to determine how much room is needed
2712      in the object file for the space records.
2713
2714      The names of the spaces are stored in a separate string table,
2715      and the index for each space into the string table is computed
2716      below.  Therefore, it is not possible to write the space headers
2717      at this time.  */
2718   num_spaces = som_count_spaces (abfd);
2719   obj_som_file_hdr (abfd)->space_location = current_offset;
2720   obj_som_file_hdr (abfd)->space_total = num_spaces;
2721   current_offset += num_spaces * sizeof (struct space_dictionary_record);
2722
2723   /* Next are the subspace records.  These are fixed length records.
2724
2725      Count the number of subspaes to determine how much room is needed
2726      in the object file for the subspace records.
2727
2728      A variety if fields in the subspace record are still unknown at
2729      this time (index into string table, fixup stream location/size, etc).  */
2730   num_subspaces = som_count_subspaces (abfd);
2731   obj_som_file_hdr (abfd)->subspace_location = current_offset;
2732   obj_som_file_hdr (abfd)->subspace_total = num_subspaces;
2733   current_offset += num_subspaces * sizeof (struct subspace_dictionary_record);
2734
2735   /* Next is the string table for the space/subspace names.  We will
2736      build and write the string table on the fly.  At the same time
2737      we will fill in the space/subspace name index fields.  */
2738
2739   /* The string table needs to be aligned on a word boundary.  */
2740   if (current_offset % 4)
2741     current_offset += (4 - (current_offset % 4));
2742
2743   /* Mark the offset of the space/subspace string table in the 
2744      file header.  */
2745   obj_som_file_hdr (abfd)->space_strings_location = current_offset;
2746
2747   /* Scribble out the space strings.  */
2748   if (som_write_space_strings (abfd, current_offset, &strings_size) == false)
2749     return false;
2750
2751   /* Record total string table size in the header and update the
2752      current offset.  */
2753   obj_som_file_hdr (abfd)->space_strings_size = strings_size;
2754   current_offset += strings_size;
2755
2756   /* Next is the symbol table.  These are fixed length records.
2757
2758      Count the number of symbols to determine how much room is needed
2759      in the object file for the symbol table.
2760
2761      The names of the symbols are stored in a separate string table,
2762      and the index for each symbol name into the string table is computed
2763      below.  Therefore, it is not possible to write the symobl table
2764      at this time.  */
2765   num_syms = bfd_get_symcount (abfd);
2766   obj_som_file_hdr (abfd)->symbol_location = current_offset;
2767   obj_som_file_hdr (abfd)->symbol_total = num_syms;
2768   current_offset += num_syms * sizeof (struct symbol_dictionary_record);
2769
2770   /* Do prep work before handling fixups.  */
2771   som_prep_for_fixups (abfd, syms, num_syms);
2772
2773   /* Next comes the fixup stream which starts on a word boundary.  */
2774   if (current_offset % 4)
2775     current_offset += (4 - (current_offset % 4)); 
2776   obj_som_file_hdr (abfd)->fixup_request_location = current_offset;
2777
2778   /* Write the fixups and update fields in subspace headers which
2779      relate to the fixup stream.  */
2780   if (som_write_fixups (abfd, current_offset, &total_reloc_size) == false)
2781     return false;
2782
2783   /* Record the total size of the fixup stream in the file header.  */
2784   obj_som_file_hdr (abfd)->fixup_request_total = total_reloc_size;
2785   current_offset += total_reloc_size;
2786
2787   /* Next are the symbol strings.
2788      Align them to a word boundary.  */
2789   if (current_offset % 4)
2790     current_offset += (4 - (current_offset % 4));
2791   obj_som_file_hdr (abfd)->symbol_strings_location = current_offset;
2792
2793   /* Scribble out the symbol strings.  */
2794   if (som_write_symbol_strings (abfd, current_offset, syms, 
2795                                 num_syms, &strings_size)
2796       == false)
2797     return false;
2798
2799   /* Record total string table size in header and update the
2800      current offset.  */
2801   obj_som_file_hdr (abfd)->symbol_strings_size = strings_size;
2802   current_offset += strings_size;
2803
2804   /* Next is the compiler records.  We do not use these.  */
2805   obj_som_file_hdr (abfd)->compiler_location = current_offset;
2806   obj_som_file_hdr (abfd)->compiler_total = 0;
2807
2808   /* Now compute the file positions for the loadable subspaces.  */
2809
2810   section = abfd->sections;
2811   for (i = 0; i < num_spaces; i++)
2812     {
2813       asection *subsection;
2814
2815       /* Find a space.  */
2816       while (som_section_data (section)->is_space == 0)
2817         section = section->next;
2818
2819       /* Now look for all its subspaces.  */
2820       for (subsection = abfd->sections;
2821            subsection != NULL;
2822            subsection = subsection->next)
2823         {
2824           
2825           if (som_section_data (subsection)->is_subspace == 0
2826               || som_section_data (subsection)->containing_space != section
2827               || (subsection->flags & SEC_ALLOC) == 0)
2828             continue;
2829
2830           som_section_data (subsection)->subspace_index = total_subspaces++;
2831           /* This is real data to be loaded from the file.  */
2832           if (subsection->flags & SEC_LOAD)
2833             {
2834               som_section_data (subsection)->subspace_dict.file_loc_init_value
2835                 = current_offset;
2836               section->filepos = current_offset;
2837               current_offset += bfd_section_size (abfd, subsection); 
2838             }
2839           /* Looks like uninitialized data.  */
2840           else
2841             {
2842               som_section_data (subsection)->subspace_dict.file_loc_init_value
2843                 = 0;
2844               som_section_data (subsection)->subspace_dict.
2845                 initialization_length = 0;
2846             }
2847         }
2848       /* Goto the next section.  */
2849       section = section->next; 
2850     }
2851
2852   /* Finally compute the file positions for unloadable subspaces.  */
2853
2854   obj_som_file_hdr (abfd)->unloadable_sp_location = current_offset;
2855   section = abfd->sections;
2856   for (i = 0; i < num_spaces; i++)
2857     {
2858       asection *subsection;
2859
2860       /* Find a space.  */
2861       while (som_section_data (section)->is_space == 0)
2862         section = section->next;
2863
2864       /* Now look for all its subspaces.  */
2865       for (subsection = abfd->sections;
2866            subsection != NULL;
2867            subsection = subsection->next)
2868         {
2869           
2870           if (som_section_data (subsection)->is_subspace == 0
2871               || som_section_data (subsection)->containing_space != section
2872               || (subsection->flags & SEC_ALLOC) != 0)
2873             continue;
2874
2875           som_section_data (subsection)->subspace_index = total_subspaces++;
2876           /* This is real data to be loaded from the file.  */
2877           if ((subsection->flags & SEC_LOAD) == 0)
2878             {
2879               som_section_data (subsection)->subspace_dict.file_loc_init_value
2880                 = current_offset;
2881               section->filepos = current_offset;
2882               current_offset += bfd_section_size (abfd, subsection); 
2883             }
2884           /* Looks like uninitialized data.  */
2885           else
2886             {
2887               som_section_data (subsection)->subspace_dict.file_loc_init_value
2888                 = 0;
2889               som_section_data (subsection)->subspace_dict.
2890                 initialization_length = bfd_section_size (abfd, subsection);
2891             }
2892         }
2893       /* Goto the next section.  */
2894       section = section->next; 
2895     }
2896
2897   obj_som_file_hdr (abfd)->unloadable_sp_size
2898     = current_offset - obj_som_file_hdr (abfd)->unloadable_sp_location;
2899
2900   /* Loader fixups are not supported in any way shape or form.  */
2901   obj_som_file_hdr (abfd)->loader_fixup_location = 0;
2902   obj_som_file_hdr (abfd)->loader_fixup_total = 0;
2903
2904   /* Done.  Store the total size of the SOM.  */
2905   obj_som_file_hdr (abfd)->som_length = current_offset;
2906   return true;
2907 }
2908
2909 /* Finally, scribble out the various headers to the disk.  */
2910
2911 static boolean
2912 som_write_headers (abfd)
2913      bfd *abfd;
2914 {
2915   int num_spaces = som_count_spaces (abfd);
2916   int i;
2917   int subspace_index = 0;
2918   file_ptr location;
2919   asection *section;
2920
2921   /* Subspaces are written first so that we can set up information
2922      about them in their containing spaces as the subspace is written.  */
2923
2924   /* Seek to the start of the subspace dictionary records.  */
2925   location = obj_som_file_hdr (abfd)->subspace_location;
2926   bfd_seek (abfd, location, SEEK_SET);
2927   section = abfd->sections;
2928   /* Now for each loadable space write out records for its subspaces.  */
2929   for (i = 0; i < num_spaces; i++)
2930     {
2931       asection *subsection;
2932
2933       /* Find a space.  */
2934       while (som_section_data (section)->is_space == 0)
2935         section = section->next;
2936
2937       /* Now look for all its subspaces.  */
2938       for (subsection = abfd->sections;
2939            subsection != NULL;
2940            subsection = subsection->next)
2941         {
2942           
2943           /* Skip any section which does not correspond to a space
2944              or subspace.  Or does not have SEC_ALLOC set (and therefore
2945              has no real bits on the disk).  */
2946           if (som_section_data (subsection)->is_subspace == 0
2947               || som_section_data (subsection)->containing_space != section
2948               || (subsection->flags & SEC_ALLOC) == 0)
2949             continue;
2950
2951           /* If this is the first subspace for this space, then save
2952              the index of the subspace in its containing space.  Also
2953              set "is_loadable" in the containing space.  */
2954
2955           if (som_section_data (section)->space_dict.subspace_quantity == 0)
2956             {
2957               som_section_data (section)->space_dict.is_loadable = 1;
2958               som_section_data (section)->space_dict.subspace_index
2959                 = subspace_index;
2960             }
2961
2962           /* Increment the number of subspaces seen and the number of
2963              subspaces contained within the current space.  */
2964           subspace_index++;
2965           som_section_data (section)->space_dict.subspace_quantity++;
2966
2967           /* Mark the index of the current space within the subspace's
2968              dictionary record.  */
2969           som_section_data (subsection)->subspace_dict.space_index = i;
2970           
2971           /* Dump the current subspace header.  */
2972           if (bfd_write ((PTR) &som_section_data (subsection)->subspace_dict,
2973                          sizeof (struct subspace_dictionary_record), 1, abfd)
2974               != sizeof (struct subspace_dictionary_record))
2975             {
2976               bfd_error = system_call_error;
2977               return false;
2978             }
2979         }
2980       /* Goto the next section.  */
2981       section = section->next; 
2982     }
2983
2984   /* Now repeat the process for unloadable subspaces.  */
2985   section = abfd->sections;
2986   /* Now for each space write out records for its subspaces.  */
2987   for (i = 0; i < num_spaces; i++)
2988     {
2989       asection *subsection;
2990
2991       /* Find a space.  */
2992       while (som_section_data (section)->is_space == 0)
2993         section = section->next;
2994
2995       /* Now look for all its subspaces.  */
2996       for (subsection = abfd->sections;
2997            subsection != NULL;
2998            subsection = subsection->next)
2999         {
3000           
3001           /* Skip any section which does not correspond to a space or
3002              subspace, or which SEC_ALLOC set (and therefore handled
3003              in the loadable spaces/subspaces code above.  */
3004
3005           if (som_section_data (subsection)->is_subspace == 0
3006               || som_section_data (subsection)->containing_space != section
3007               || (subsection->flags & SEC_ALLOC) != 0)
3008             continue;
3009
3010           /* If this is the first subspace for this space, then save
3011              the index of the subspace in its containing space.  Clear
3012              "is_loadable".  */
3013
3014           if (som_section_data (section)->space_dict.subspace_quantity == 0)
3015             {
3016               som_section_data (section)->space_dict.is_loadable = 0;
3017               som_section_data (section)->space_dict.subspace_index
3018                 = subspace_index;
3019             }
3020
3021           /* Increment the number of subspaces seen and the number of
3022              subspaces contained within the current space.  */
3023           som_section_data (section)->space_dict.subspace_quantity++;
3024           subspace_index++; 
3025
3026           /* Mark the index of the current space within the subspace's
3027              dictionary record.  */
3028           som_section_data (subsection)->subspace_dict.space_index = i;
3029           
3030           /* Dump this subspace header.  */
3031           if (bfd_write ((PTR) &som_section_data (subsection)->subspace_dict,
3032                          sizeof (struct subspace_dictionary_record), 1, abfd)
3033               != sizeof (struct subspace_dictionary_record))
3034             {
3035               bfd_error = system_call_error;
3036               return false;
3037             }
3038         }
3039       /* Goto the next section.  */
3040       section = section->next; 
3041     }
3042
3043   /* All the subspace dictiondary records are written, and all the
3044      fields are set up in the space dictionary records.
3045
3046      Seek to the right location and start writing the space
3047      dictionary records.  */
3048   location = obj_som_file_hdr (abfd)->space_location;
3049   bfd_seek (abfd, location, SEEK_SET);
3050
3051   section = abfd->sections;
3052   for (i = 0; i < num_spaces; i++)
3053     {
3054
3055       /* Find a space.  */
3056       while (som_section_data (section)->is_space == 0)
3057         section = section->next;
3058
3059       /* Dump its header  */
3060       if (bfd_write ((PTR) &som_section_data (section)->space_dict,
3061                      sizeof (struct space_dictionary_record), 1, abfd)
3062           != sizeof (struct space_dictionary_record))
3063         {
3064           bfd_error = system_call_error;
3065           return false;
3066         }
3067
3068       /* Goto the next section.  */
3069       section = section->next;
3070     }
3071
3072   /* Only thing left to do is write out the file header.  It is always
3073      at location zero.  Seek there and write it.  */
3074   bfd_seek (abfd, (file_ptr) 0, SEEK_SET);
3075   if (bfd_write ((PTR) obj_som_file_hdr (abfd),
3076                  sizeof (struct header), 1, abfd)
3077       != sizeof (struct header))
3078     {
3079       bfd_error = system_call_error;
3080       return false;
3081     }
3082   return true;
3083 }
3084
3085 /* Compute and return the checksum for a SOM file header.  */
3086
3087 static unsigned long
3088 som_compute_checksum (abfd)
3089      bfd *abfd;
3090 {
3091   unsigned long checksum, count, i;
3092   unsigned long *buffer = (unsigned long *) obj_som_file_hdr (abfd);
3093
3094   checksum = 0;
3095   count = sizeof (struct header) / sizeof (unsigned long);
3096   for (i = 0; i < count; i++)
3097     checksum ^= *(buffer + i);
3098
3099   return checksum;
3100 }
3101
3102 static void
3103 som_bfd_derive_misc_symbol_info (abfd, sym, info)
3104      bfd *abfd;
3105      asymbol *sym;
3106      struct som_misc_symbol_info *info;
3107 {
3108   /* Initialize.  */
3109   memset (info, 0, sizeof (struct som_misc_symbol_info));
3110
3111   /* The HP SOM linker requires detailed type information about
3112      all symbols (including undefined symbols!).  Unfortunately,
3113      the type specified in an import/export statement does not
3114      always match what the linker wants.  Severe braindamage.  */
3115          
3116   /* Section symbols will not have a SOM symbol type assigned to
3117      them yet.  Assign all section symbols type ST_DATA.  */
3118   if (sym->flags & BSF_SECTION_SYM)
3119     info->symbol_type = ST_DATA;
3120   else
3121     {
3122       /* Common symbols must have scope SS_UNSAT and type
3123          ST_STORAGE or the linker will choke.  */
3124       if (sym->section == &bfd_com_section)
3125         {
3126           info->symbol_scope = SS_UNSAT;
3127           info->symbol_type = ST_STORAGE;
3128         }
3129
3130       /* It is possible to have a symbol without an associated
3131          type.  This happens if the user imported the symbol
3132          without a type and the symbol was never defined
3133          locally.  If BSF_FUNCTION is set for this symbol, then
3134          assign it type ST_CODE (the HP linker requires undefined
3135          external functions to have type ST_CODE rather than ST_ENTRY).  */
3136       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN
3137                && sym->section == &bfd_und_section
3138                && sym->flags & BSF_FUNCTION)
3139         info->symbol_type = ST_CODE;
3140
3141       /* Handle function symbols which were defined in this file.
3142          They should have type ST_ENTRY.  Also retrieve the argument
3143          relocation bits from the SOM backend information.  */
3144       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_ENTRY
3145                || (som_symbol_data (sym)->som_type == SYMBOL_TYPE_CODE
3146                    && (sym->flags & BSF_FUNCTION))
3147                || (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN
3148                    && (sym->flags & BSF_FUNCTION)))
3149         {
3150           info->symbol_type = ST_ENTRY;
3151           info->arg_reloc = som_symbol_data (sym)->tc_data.hppa_arg_reloc;
3152         }
3153
3154       /* If the type is unknown at this point, it should be
3155          ST_DATA (functions were handled as special cases above).  */
3156       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN)
3157         info->symbol_type = ST_DATA;
3158
3159       /* From now on it's a very simple mapping.  */
3160       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_ABSOLUTE)
3161         info->symbol_type = ST_ABSOLUTE;
3162       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_CODE)
3163         info->symbol_type = ST_CODE;
3164       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_DATA)
3165         info->symbol_type = ST_DATA;
3166       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_MILLICODE)
3167         info->symbol_type = ST_MILLICODE;
3168       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_PLABEL)
3169         info->symbol_type = ST_PLABEL;
3170       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_PRI_PROG)
3171         info->symbol_type = ST_PRI_PROG;
3172       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_SEC_PROG)
3173         info->symbol_type = ST_SEC_PROG;
3174     }
3175         
3176   /* Now handle the symbol's scope.  Exported data which is not
3177      in the common section has scope SS_UNIVERSAL.  Note scope
3178      of common symbols was handled earlier!  */
3179   if (sym->flags & BSF_EXPORT && sym->section != &bfd_com_section)
3180     info->symbol_scope = SS_UNIVERSAL;
3181   /* Any undefined symbol at this point has a scope SS_UNSAT.  */
3182   else if (sym->section == &bfd_und_section)
3183     info->symbol_scope = SS_UNSAT;
3184   /* Anything else which is not in the common section has scope
3185      SS_LOCAL.  */
3186   else if (sym->section != &bfd_com_section)
3187     info->symbol_scope = SS_LOCAL;
3188
3189   /* Now set the symbol_info field.  It has no real meaning
3190      for undefined or common symbols, but the HP linker will
3191      choke if it's not set to some "reasonable" value.  We
3192      use zero as a reasonable value.  */
3193   if (sym->section == &bfd_com_section || sym->section == &bfd_und_section)
3194     info->symbol_info = 0;
3195   /* For all other symbols, the symbol_info field contains the 
3196      subspace index of the space this symbol is contained in.  */
3197   else
3198     info->symbol_info = som_section_data (sym->section)->subspace_index;
3199
3200   /* Set the symbol's value.  */
3201   info->symbol_value = sym->value + sym->section->vma;
3202 }
3203
3204 /* Build and write, in one big chunk, the entire symbol table for
3205    this BFD.  */
3206
3207 static boolean
3208 som_build_and_write_symbol_table (abfd)
3209      bfd *abfd;
3210 {
3211   unsigned int num_syms = bfd_get_symcount (abfd);
3212   file_ptr symtab_location = obj_som_file_hdr (abfd)->symbol_location;
3213   asymbol **bfd_syms = bfd_get_outsymbols (abfd);
3214   struct symbol_dictionary_record *som_symtab;
3215   int i, symtab_size;
3216
3217   /* Compute total symbol table size and allocate a chunk of memory
3218      to hold the symbol table as we build it.  */
3219   symtab_size = num_syms * sizeof (struct symbol_dictionary_record);
3220   som_symtab = (struct symbol_dictionary_record *) alloca (symtab_size);
3221   memset (som_symtab, 0, symtab_size);
3222
3223   /* Walk over each symbol.  */
3224   for (i = 0; i < num_syms; i++)
3225     {
3226       struct som_misc_symbol_info info;
3227
3228       /* This is really an index into the symbol strings table.  
3229          By the time we get here, the index has already been 
3230          computed and stored into the name field in the BFD symbol.  */
3231       som_symtab[i].name.n_strx = (int) bfd_syms[i]->name;
3232
3233       /* Derive SOM information from the BFD symbol.  */
3234       som_bfd_derive_misc_symbol_info (abfd, bfd_syms[i], &info);
3235
3236       /* Now use it.  */
3237       som_symtab[i].symbol_type = info.symbol_type;
3238       som_symtab[i].symbol_scope = info.symbol_scope;
3239       som_symtab[i].arg_reloc = info.arg_reloc;
3240       som_symtab[i].symbol_info = info.symbol_info;
3241       som_symtab[i].symbol_value = info.symbol_value;
3242     }
3243
3244   /* Everything is ready, seek to the right location and
3245      scribble out the symbol table.  */
3246   if (bfd_seek (abfd, symtab_location, SEEK_SET) != 0)
3247     {
3248       bfd_error = system_call_error;
3249       return false;
3250     }
3251
3252   if (bfd_write ((PTR) som_symtab, symtab_size, 1, abfd) != symtab_size)
3253     {
3254       bfd_error  = system_call_error;
3255       return false;
3256     }
3257   return true; 
3258 }
3259
3260 /* Write an object in SOM format.  */  
3261
3262 static boolean
3263 som_write_object_contents (abfd)
3264      bfd *abfd;
3265 {
3266   if (abfd->output_has_begun == false)
3267     {
3268       /* Set up fixed parts of the file, space, and subspace headers.
3269          Notify the world that output has begun.  */
3270       som_prep_headers (abfd);
3271       abfd->output_has_begun = true;
3272       /* Start writing the object file.  This include all the string
3273          tables, fixup streams, and other portions of the object file.  */
3274       som_begin_writing (abfd);
3275     }
3276
3277   /* Now that the symbol table information is complete, build and
3278      write the symbol table.  */
3279   if (som_build_and_write_symbol_table (abfd) == false)
3280     return false;
3281
3282   /* Compute the checksum for the file header just before writing
3283      the header to disk.  */
3284   obj_som_file_hdr (abfd)->checksum = som_compute_checksum (abfd);
3285   return (som_write_headers (abfd));
3286 }
3287
3288 \f
3289 /* Read and save the string table associated with the given BFD.  */
3290
3291 static boolean
3292 som_slurp_string_table (abfd)
3293      bfd *abfd;
3294 {
3295   char *stringtab;
3296
3297   /* Use the saved version if its available.  */
3298   if (obj_som_stringtab (abfd) != NULL)
3299     return true;
3300
3301   /* Allocate and read in the string table.  */
3302   stringtab = bfd_zalloc (abfd, obj_som_stringtab_size (abfd));
3303   if (stringtab == NULL)
3304     {
3305       bfd_error = no_memory;
3306       return false;
3307     }
3308
3309   if (bfd_seek (abfd, obj_som_str_filepos (abfd), SEEK_SET) < 0)
3310     {
3311       bfd_error = system_call_error;
3312       return false;
3313     }
3314   
3315   if (bfd_read (stringtab, obj_som_stringtab_size (abfd), 1, abfd)
3316       != obj_som_stringtab_size (abfd))
3317     {
3318       bfd_error = system_call_error;
3319       return false;
3320     }
3321
3322   /* Save our results and return success. */
3323   obj_som_stringtab (abfd) = stringtab;
3324   return true;
3325 }
3326
3327 /* Return the amount of data (in bytes) required to hold the symbol
3328    table for this object.  */
3329
3330 static unsigned int
3331 som_get_symtab_upper_bound (abfd)
3332      bfd *abfd;
3333 {
3334   if (!som_slurp_symbol_table (abfd))
3335     return 0;
3336
3337   return (bfd_get_symcount (abfd) + 1) * (sizeof (som_symbol_type *));
3338 }
3339
3340 /* Convert from a SOM subspace index to a BFD section.  */
3341
3342 static asection *
3343 som_section_from_subspace_index (abfd, index)
3344      bfd *abfd;
3345      unsigned int index;
3346 {
3347   asection *section;
3348
3349   for (section = abfd->sections; section != NULL; section = section->next)
3350     if (som_section_data (section)->subspace_index == index)
3351       return section;
3352
3353   /* Should never happen.  */
3354   abort();
3355 }
3356
3357 /* Read and save the symbol table associated with the given BFD.  */
3358
3359 static unsigned int
3360 som_slurp_symbol_table (abfd)
3361      bfd *abfd;
3362 {
3363   int symbol_count = bfd_get_symcount (abfd);
3364   int symsize = sizeof (struct symbol_dictionary_record);
3365   char *stringtab;
3366   struct symbol_dictionary_record *buf, *bufp, *endbufp;
3367   som_symbol_type *sym, *symbase;
3368
3369   /* Return saved value if it exists.  */
3370   if (obj_som_symtab (abfd) != NULL)
3371     return true;
3372
3373   /* Special case.  This is *not* an error.  */
3374   if (symbol_count == 0)
3375     return true;
3376
3377   if (!som_slurp_string_table (abfd))
3378     return false;
3379
3380   stringtab = obj_som_stringtab (abfd);
3381
3382   symbase = (som_symbol_type *)
3383     bfd_zalloc (abfd, symbol_count * sizeof (som_symbol_type));
3384   if (symbase == NULL)
3385     {
3386       bfd_error = no_memory;
3387       return false;
3388     }
3389
3390   /* Read in the external SOM representation.  */
3391   buf = alloca (symbol_count * symsize);
3392   if (buf == NULL)
3393     {
3394       bfd_error = no_memory;
3395       return false;
3396     }
3397   if (bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET) < 0)
3398     {
3399       bfd_error = system_call_error;
3400       return false;
3401     }
3402   if (bfd_read (buf, symbol_count * symsize, 1, abfd) 
3403       != symbol_count * symsize)
3404     {
3405       bfd_error = no_symbols;
3406       return (false);
3407     }
3408
3409   /* Iterate over all the symbols and internalize them.  */
3410   endbufp = buf + symbol_count;
3411   for (bufp = buf, sym = symbase; bufp < endbufp; ++bufp)
3412     {
3413
3414       /* I don't think we care about these.  */
3415       if (bufp->symbol_type == ST_SYM_EXT
3416           || bufp->symbol_type == ST_ARG_EXT)
3417         continue;
3418
3419       /* Set some private data we care about.  */
3420       if (bufp->symbol_type == ST_NULL)
3421         som_symbol_data (sym)->som_type = SYMBOL_TYPE_UNKNOWN;
3422       else if (bufp->symbol_type == ST_ABSOLUTE)
3423         som_symbol_data (sym)->som_type = SYMBOL_TYPE_ABSOLUTE;
3424       else if (bufp->symbol_type == ST_DATA)
3425         som_symbol_data (sym)->som_type = SYMBOL_TYPE_DATA;
3426       else if (bufp->symbol_type == ST_CODE)
3427         som_symbol_data (sym)->som_type = SYMBOL_TYPE_CODE;
3428       else if (bufp->symbol_type == ST_PRI_PROG)
3429         som_symbol_data (sym)->som_type = SYMBOL_TYPE_PRI_PROG;
3430       else if (bufp->symbol_type == ST_SEC_PROG)
3431         som_symbol_data (sym)->som_type = SYMBOL_TYPE_SEC_PROG;
3432       else if (bufp->symbol_type == ST_ENTRY)
3433         som_symbol_data (sym)->som_type = SYMBOL_TYPE_ENTRY;
3434       else if (bufp->symbol_type == ST_MILLICODE)
3435         som_symbol_data (sym)->som_type = SYMBOL_TYPE_MILLICODE;
3436       else if (bufp->symbol_type == ST_PLABEL)
3437         som_symbol_data (sym)->som_type = SYMBOL_TYPE_PLABEL;
3438       else
3439         som_symbol_data (sym)->som_type = SYMBOL_TYPE_UNKNOWN;
3440       som_symbol_data (sym)->tc_data.hppa_arg_reloc = bufp->arg_reloc;
3441
3442       /* Some reasonable defaults.  */
3443       sym->symbol.the_bfd = abfd;
3444       sym->symbol.name = bufp->name.n_strx + stringtab;
3445       sym->symbol.value = bufp->symbol_value;
3446       sym->symbol.section = 0;
3447       sym->symbol.flags = 0;
3448
3449       switch (bufp->symbol_type)
3450         {
3451         case ST_ENTRY:
3452         case ST_PRI_PROG:
3453         case ST_SEC_PROG:
3454         case ST_MILLICODE:
3455           sym->symbol.flags |= BSF_FUNCTION;
3456           sym->symbol.value &= ~0x3;
3457           break;
3458
3459         case ST_STUB:
3460         case ST_CODE:
3461           sym->symbol.value &= ~0x3;
3462
3463         default:
3464           break;
3465         }
3466
3467       /* Handle scoping and section information.  */
3468       switch (bufp->symbol_scope)
3469         {
3470         /* symbol_info field is undefined for SS_EXTERNAL and SS_UNSAT symbols,
3471            so the section associated with this symbol can't be known.  */
3472         case SS_EXTERNAL:
3473         case SS_UNSAT:
3474           if (bufp->symbol_type != ST_STORAGE)
3475             sym->symbol.section = &bfd_und_section;
3476           else
3477             sym->symbol.section = &bfd_com_section;
3478           sym->symbol.flags |= (BSF_EXPORT | BSF_GLOBAL);
3479           break;
3480
3481         case SS_UNIVERSAL:
3482           sym->symbol.flags |= (BSF_EXPORT | BSF_GLOBAL);
3483           sym->symbol.section
3484             = som_section_from_subspace_index (abfd, bufp->symbol_info);
3485           sym->symbol.value -= sym->symbol.section->vma;
3486           break;
3487
3488 #if 0
3489         /* SS_GLOBAL and SS_LOCAL are two names for the same thing.
3490            Sound dumb?  It is.  */
3491         case SS_GLOBAL:
3492 #endif
3493         case SS_LOCAL:
3494           sym->symbol.flags |= BSF_LOCAL;
3495           sym->symbol.section
3496             = som_section_from_subspace_index (abfd, bufp->symbol_info);
3497           sym->symbol.value -= sym->symbol.section->vma;
3498           break;
3499         }
3500
3501       /* Mark symbols left around by the debugger.  */
3502       if (strlen (sym->symbol.name) >= 2
3503           && sym->symbol.name[0] == 'L'
3504           && (sym->symbol.name[1] == '$' || sym->symbol.name[2] == '$'
3505               || sym->symbol.name[3] == '$'))
3506         sym->symbol.flags |= BSF_DEBUGGING;
3507
3508       /* Note increment at bottom of loop, since we skip some symbols
3509          we can not include it as part of the for statement.  */
3510       sym++;
3511     }
3512
3513   /* Save our results and return success.  */
3514   obj_som_symtab (abfd) = symbase;
3515   return (true);
3516 }
3517
3518 /* Canonicalize a SOM symbol table.  Return the number of entries
3519    in the symbol table.  */
3520
3521 static unsigned int
3522 som_get_symtab (abfd, location)
3523      bfd *abfd;
3524      asymbol **location;
3525 {
3526   int i;
3527   som_symbol_type *symbase;
3528
3529   if (!som_slurp_symbol_table (abfd))
3530     return 0;
3531
3532   i = bfd_get_symcount (abfd);
3533   symbase = obj_som_symtab (abfd);
3534
3535   for (; i > 0; i--, location++, symbase++)
3536     *location = &symbase->symbol;
3537
3538   /* Final null pointer.  */
3539   *location = 0;
3540   return (bfd_get_symcount (abfd));
3541 }
3542
3543 /* Make a SOM symbol.  There is nothing special to do here.  */
3544
3545 static asymbol *
3546 som_make_empty_symbol (abfd)
3547      bfd *abfd;
3548 {
3549   som_symbol_type *new =
3550   (som_symbol_type *) bfd_zalloc (abfd, sizeof (som_symbol_type));
3551   if (new == NULL)
3552     {
3553       bfd_error = no_memory;
3554       return 0;
3555     }
3556   new->symbol.the_bfd = abfd;
3557
3558   return &new->symbol;
3559 }
3560
3561 /* Print symbol information.  */
3562
3563 static void
3564 som_print_symbol (ignore_abfd, afile, symbol, how)
3565      bfd *ignore_abfd;
3566      PTR afile;
3567      asymbol *symbol;
3568      bfd_print_symbol_type how;
3569 {
3570   FILE *file = (FILE *) afile;
3571   switch (how)
3572     {
3573     case bfd_print_symbol_name:
3574       fprintf (file, "%s", symbol->name);
3575       break;
3576     case bfd_print_symbol_more:
3577       fprintf (file, "som ");
3578       fprintf_vma (file, symbol->value);
3579       fprintf (file, " %lx", (long) symbol->flags);
3580       break;
3581     case bfd_print_symbol_all:
3582       {
3583         CONST char *section_name;
3584         section_name = symbol->section ? symbol->section->name : "(*none*)";
3585         bfd_print_symbol_vandf ((PTR) file, symbol);
3586         fprintf (file, " %s\t%s", section_name, symbol->name);
3587         break;
3588       }
3589     }
3590 }
3591
3592 /* Count or process variable-length SOM fixup records.
3593
3594    To avoid code duplication we use this code both to compute the number
3595    of relocations requested by a stream, and to internalize the stream.
3596
3597    When computing the number of relocations requested by a stream the
3598    variables rptr, section, and symbols have no meaning.
3599
3600    Return the number of relocations requested by the fixup stream.  When
3601    not just counting 
3602
3603    This needs at least two or three more passes to get it cleaned up.  */
3604
3605 static unsigned int
3606 som_set_reloc_info (fixup, end, internal_relocs, section, symbols, just_count)
3607      unsigned char *fixup;
3608      unsigned int end;
3609      arelent *internal_relocs;
3610      asection *section;
3611      asymbol **symbols;
3612      boolean just_count;
3613 {
3614   unsigned int op, varname;
3615   unsigned char *end_fixups = &fixup[end];
3616   const struct fixup_format *fp;
3617   char *cp;
3618   unsigned char *save_fixup;
3619   int variables[26], stack[20], c, v, count, prev_fixup, *sp;
3620   const int *subop;
3621   arelent *rptr= internal_relocs;
3622   unsigned int offset = just_count ? 0 : section->vma;
3623
3624 #define var(c)          variables[(c) - 'A']
3625 #define push(v)         (*sp++ = (v))
3626 #define pop()           (*--sp)
3627 #define emptystack()    (sp == stack)
3628
3629   som_initialize_reloc_queue (reloc_queue);
3630   memset (variables, 0, sizeof (variables));
3631   memset (stack, 0, sizeof (stack));
3632   count = 0;
3633   prev_fixup = 0;
3634   sp = stack;
3635
3636   while (fixup < end_fixups)
3637     {
3638
3639       /* Save pointer to the start of this fixup.  We'll use
3640          it later to determine if it is necessary to put this fixup
3641          on the queue.  */
3642       save_fixup = fixup;
3643
3644       /* Get the fixup code and its associated format.  */
3645       op = *fixup++;
3646       fp = &som_fixup_formats[op];
3647
3648       /* Handle a request for a previous fixup.  */
3649       if (*fp->format == 'P')
3650         {
3651           /* Get pointer to the beginning of the prev fixup, move
3652              the repeated fixup to the head of the queue.  */
3653           fixup = reloc_queue[fp->D].reloc;
3654           som_reloc_queue_fix (reloc_queue, fp->D);
3655           prev_fixup = 1;
3656
3657           /* Get the fixup code and its associated format.  */
3658           op = *fixup++;
3659           fp = &som_fixup_formats[op];
3660         }
3661
3662       /* If we are not just counting, set some reasonable defaults.  */
3663       if (! just_count)
3664         {
3665           rptr->address = offset;
3666           rptr->howto = &som_hppa_howto_table[op];
3667           rptr->addend = 0;
3668           rptr->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr;
3669         }
3670
3671       /* Set default input length to 0.  Get the opcode class index
3672          into D.  */
3673       var ('L') = 0;
3674       var ('D') = fp->D;
3675
3676       /* Get the opcode format.  */
3677       cp = fp->format;
3678
3679       /* Process the format string.  Parsing happens in two phases,
3680          parse RHS, then assign to LHS.  Repeat until no more 
3681          characters in the format string.  */
3682       while (*cp)
3683         {
3684           /* The variable this pass is going to compute a value for.  */
3685           varname = *cp++;
3686
3687           /* Start processing RHS.  Continue until a NULL or '=' is found.  */
3688           do
3689             {
3690               c = *cp++;
3691
3692               /* If this is a variable, push it on the stack.  */
3693               if (isupper (c))
3694                 push (var (c));
3695
3696               /* If this is a lower case letter, then it represents
3697                  additional data from the fixup stream to be pushed onto
3698                  the stack.  */
3699               else if (islower (c))
3700                 {
3701                   for (v = 0; c > 'a'; --c)
3702                     v = (v << 8) | *fixup++;
3703                   push (v);
3704                 }
3705
3706               /* A decimal constant.  Push it on the stack.  */
3707               else if (isdigit (c))
3708                 {
3709                   v = c - '0';
3710                   while (isdigit (*cp))
3711                     v = (v * 10) + (*cp++ - '0');
3712                   push (v);
3713                 }
3714               else
3715
3716                 /* An operator.  Pop two two values from the stack and
3717                    use them as operands to the given operation.  Push
3718                    the result of the operation back on the stack.  */
3719                 switch (c)
3720                   {
3721                   case '+':
3722                     v = pop ();
3723                     v += pop ();
3724                     push (v);
3725                     break;
3726                   case '*':
3727                     v = pop ();
3728                     v *= pop ();
3729                     push (v);
3730                     break;
3731                   case '<':
3732                     v = pop ();
3733                     v = pop () << v;
3734                     push (v);
3735                     break;
3736                   default:
3737                     abort ();
3738                   }
3739             }
3740           while (*cp && *cp != '=');
3741
3742           /* Move over the equal operator.  */
3743           cp++;
3744
3745           /* Pop the RHS off the stack.  */
3746           c = pop ();
3747
3748           /* Perform the assignment.  */
3749           var (varname) = c;
3750
3751           /* Handle side effects. and special 'O' stack cases.  */
3752           switch (varname)
3753             {
3754             /* Consume some bytes from the input space.  */
3755             case 'L':
3756               offset += c;
3757               break;
3758             /* A symbol to use in the relocation.  Make a note
3759                of this if we are not just counting.  */
3760             case 'S':
3761               if (! just_count)
3762                 rptr->sym_ptr_ptr = &symbols[c];
3763               break;
3764             /* Handle the linker expression stack.  */
3765             case 'O':
3766               switch (op)
3767                 {
3768                 case R_COMP1:
3769                   subop = comp1_opcodes;
3770                   break;
3771                 case R_COMP2:
3772                   subop = comp2_opcodes;
3773                   break;
3774                 case R_COMP3:
3775                   subop = comp3_opcodes;
3776                   break;
3777                 default:
3778                   abort ();
3779                 }
3780               while (*subop <= (unsigned char) c)
3781                 ++subop;
3782               --subop;
3783               break;
3784             default:
3785               break;
3786             }
3787         }
3788
3789       /* If we used a previous fixup, clean up after it.  */
3790       if (prev_fixup)
3791         {
3792           fixup = save_fixup + 1;
3793           prev_fixup = 0;
3794         }
3795       /* Queue it.  */
3796       else if (fixup > save_fixup + 1)
3797         som_reloc_queue_insert (save_fixup, fixup - save_fixup, reloc_queue);
3798
3799       /* We do not pass R_DATA_OVERRIDE or R_NO_RELOCATION 
3800          fixups to BFD.  */
3801       if (som_hppa_howto_table[op].type != R_DATA_OVERRIDE
3802           && som_hppa_howto_table[op].type != R_NO_RELOCATION)
3803         {
3804           /* Done with a single reloction. Loop back to the top.  */
3805           if (! just_count)
3806             {
3807               rptr->addend = var ('V');
3808               rptr++;
3809             }
3810           count++;
3811           /* Now that we've handled a "full" relocation, reset
3812              some state.  */
3813           memset (variables, 0, sizeof (variables));
3814           memset (stack, 0, sizeof (stack));
3815         }
3816     }
3817   return count;
3818
3819 #undef var
3820 #undef push
3821 #undef pop
3822 #undef emptystack
3823 }
3824
3825 /* Read in the relocs (aka fixups in SOM terms) for a section. 
3826
3827    som_get_reloc_upper_bound calls this routine with JUST_COUNT 
3828    set to true to indicate it only needs a count of the number
3829    of actual relocations.  */
3830
3831 static boolean
3832 som_slurp_reloc_table (abfd, section, symbols, just_count)
3833      bfd *abfd;
3834      asection *section;
3835      asymbol **symbols;
3836      boolean just_count;
3837 {
3838   char *external_relocs;
3839   unsigned int fixup_stream_size;
3840   arelent *internal_relocs;
3841   unsigned int num_relocs;
3842
3843   fixup_stream_size = som_section_data (section)->reloc_size;
3844   /* If there were no relocations, then there is nothing to do.  */
3845   if (section->reloc_count == 0)
3846     return true;
3847
3848   /* If reloc_count is -1, then the relocation stream has not been 
3849      parsed.  We must do so now to know how many relocations exist.  */
3850   if (section->reloc_count == -1)
3851     {
3852       external_relocs = (char *) bfd_zalloc (abfd, fixup_stream_size);
3853       if (external_relocs == (char *) NULL)
3854         {
3855           bfd_error = no_memory;
3856           return false;
3857         }
3858       /* Read in the external forms. */
3859       if (bfd_seek (abfd,
3860                     obj_som_reloc_filepos (abfd) + section->rel_filepos,
3861                     SEEK_SET)
3862           != 0)
3863         {
3864           bfd_error = system_call_error;
3865           return false;
3866         }
3867       if (bfd_read (external_relocs, 1, fixup_stream_size, abfd)
3868           != fixup_stream_size)
3869         {
3870           bfd_error = system_call_error;
3871           return false;
3872         }
3873       /* Let callers know how many relocations found.
3874          also save the relocation stream as we will
3875          need it again.  */
3876       section->reloc_count = som_set_reloc_info (external_relocs,
3877                                                  fixup_stream_size,
3878                                                  NULL, NULL, NULL, true);
3879
3880       som_section_data (section)->reloc_stream = external_relocs;
3881     }
3882
3883   /* If the caller only wanted a count, then return now.  */
3884   if (just_count)
3885     return true;
3886
3887   num_relocs = section->reloc_count;
3888   external_relocs = som_section_data (section)->reloc_stream;
3889   /* Return saved information about the relocations if it is available.  */
3890   if (section->relocation != (arelent *) NULL)
3891     return true;
3892
3893   internal_relocs = (arelent *) bfd_zalloc (abfd,
3894                                             num_relocs * sizeof (arelent));
3895   if (internal_relocs == (arelent *) NULL)
3896     {
3897       bfd_error = no_memory;
3898       return false;
3899     }
3900
3901   /* Process and internalize the relocations.  */
3902   som_set_reloc_info (external_relocs, fixup_stream_size,
3903                       internal_relocs, section, symbols, false);
3904
3905   /* Save our results and return success.  */
3906   section->relocation = internal_relocs;
3907   return (true);
3908 }
3909
3910 /* Return the number of bytes required to store the relocation
3911    information associated with the given section.  */ 
3912
3913 static unsigned int
3914 som_get_reloc_upper_bound (abfd, asect)
3915      bfd *abfd;
3916      sec_ptr asect;
3917 {
3918   /* If section has relocations, then read in the relocation stream
3919      and parse it to determine how many relocations exist.  */
3920   if (asect->flags & SEC_RELOC)
3921     {
3922       if (som_slurp_reloc_table (abfd, asect, NULL, true))
3923         return (asect->reloc_count + 1) * sizeof (arelent);
3924     }
3925   /* Either there are no relocations or an error occurred while 
3926      reading and parsing the relocation stream.  */ 
3927   return 0;
3928 }
3929
3930 /* Convert relocations from SOM (external) form into BFD internal
3931    form.  Return the number of relocations.  */
3932
3933 static unsigned int
3934 som_canonicalize_reloc (abfd, section, relptr, symbols)
3935      bfd *abfd;
3936      sec_ptr section;
3937      arelent **relptr;
3938      asymbol **symbols;
3939 {
3940   arelent *tblptr;
3941   int count;
3942
3943   if (som_slurp_reloc_table (abfd, section, symbols, false) == false)
3944     return 0;
3945
3946   count = section->reloc_count;
3947   tblptr = section->relocation;
3948   if (tblptr == (arelent *) NULL)
3949     return 0;
3950
3951   while (count--)
3952     *relptr++ = tblptr++;
3953
3954   *relptr = (arelent *) NULL;
3955   return section->reloc_count;
3956 }
3957
3958 extern bfd_target som_vec;
3959
3960 /* A hook to set up object file dependent section information.  */
3961
3962 static boolean
3963 som_new_section_hook (abfd, newsect)
3964      bfd *abfd;
3965      asection *newsect;
3966 {
3967   newsect->used_by_bfd =
3968     (PTR) bfd_zalloc (abfd, sizeof (struct som_section_data_struct));
3969   if (!newsect->used_by_bfd)
3970     {
3971       bfd_error = no_memory;
3972       return false;
3973     }
3974   newsect->alignment_power = 3;
3975
3976   /* Initialize the subspace_index field to -1 so that it does
3977      not match a subspace with an index of 0.  */
3978   som_section_data (newsect)->subspace_index = -1;
3979
3980   /* We allow more than three sections internally */
3981   return true;
3982 }
3983
3984 /* Set backend info for sections which can not be described
3985    in the BFD data structures.  */
3986
3987 void
3988 bfd_som_set_section_attributes (section, defined, private, sort_key, spnum)
3989      asection *section;
3990      int defined;
3991      int private;
3992      unsigned char sort_key;
3993      int spnum;
3994 {
3995   struct space_dictionary_record *space_dict;
3996
3997   som_section_data (section)->is_space = 1;
3998   space_dict = &som_section_data (section)->space_dict;
3999   space_dict->is_defined = defined;
4000   space_dict->is_private = private;
4001   space_dict->sort_key = sort_key;
4002   space_dict->space_number = spnum;
4003 }
4004
4005 /* Set backend info for subsections which can not be described 
4006    in the BFD data structures.  */
4007
4008 void
4009 bfd_som_set_subsection_attributes (section, container, access,
4010                                    sort_key, quadrant)
4011      asection *section;
4012      asection *container;
4013      int access;
4014      unsigned int sort_key;
4015      int quadrant;
4016 {
4017   struct subspace_dictionary_record *subspace_dict;
4018   som_section_data (section)->is_subspace = 1;
4019   subspace_dict = &som_section_data (section)->subspace_dict;
4020   subspace_dict->access_control_bits = access;
4021   subspace_dict->sort_key = sort_key;
4022   subspace_dict->quadrant = quadrant;
4023   som_section_data (section)->containing_space = container;
4024 }
4025
4026 /* Set the full SOM symbol type.  SOM needs far more symbol information
4027    than any other object file format I'm aware of.  It is mandatory
4028    to be able to know if a symbol is an entry point, millicode, data,
4029    code, absolute, storage request, or procedure label.  If you get
4030    the symbol type wrong your program will not link.  */
4031
4032 void
4033 bfd_som_set_symbol_type (symbol, type)
4034      asymbol *symbol;
4035      unsigned int type;
4036 {
4037   som_symbol_data (symbol)->som_type = type;
4038 }
4039
4040 /* Attach 64bits of unwind information to a symbol (which hopefully
4041    is a function of some kind!).  It would be better to keep this
4042    in the R_ENTRY relocation, but there is not enough space.  */
4043
4044 void
4045 bfd_som_attach_unwind_info (symbol, unwind_desc)
4046      asymbol *symbol;
4047      char *unwind_desc;
4048 {
4049   som_symbol_data (symbol)->unwind = unwind_desc;
4050 }
4051
4052 /* Attach an auxiliary header to the BFD backend so that it may be
4053    written into the object file.  */
4054 void
4055 bfd_som_attach_aux_hdr (abfd, type, string)
4056      bfd *abfd;
4057      int type;
4058      char *string;
4059 {
4060   if (type == VERSION_AUX_ID)
4061     {
4062       int len = strlen (string);
4063       int pad = 0;
4064
4065       if (len % 4)
4066         pad = (4 - (len % 4));
4067       obj_som_version_hdr (abfd) = (struct user_string_aux_hdr *)
4068         bfd_zalloc (abfd, sizeof (struct aux_id)
4069                               + sizeof (unsigned int) + len + pad);
4070       if (!obj_som_version_hdr (abfd))
4071         {
4072           bfd_error = no_memory;
4073           abort();              /* FIXME */
4074         }
4075       obj_som_version_hdr (abfd)->header_id.type = VERSION_AUX_ID;
4076       obj_som_version_hdr (abfd)->header_id.length = len + pad;
4077       obj_som_version_hdr (abfd)->header_id.length += sizeof (int);
4078       obj_som_version_hdr (abfd)->string_length = len;
4079       strncpy (obj_som_version_hdr (abfd)->user_string, string, len);
4080     }
4081   else if (type == COPYRIGHT_AUX_ID)
4082     {
4083       int len = strlen (string);
4084       int pad = 0;
4085
4086       if (len % 4)
4087         pad = (4 - (len % 4));
4088       obj_som_copyright_hdr (abfd) = (struct copyright_aux_hdr *)
4089         bfd_zalloc (abfd, sizeof (struct aux_id)
4090                             + sizeof (unsigned int) + len + pad);
4091       if (!obj_som_copyright_hdr (abfd))
4092         {
4093           bfd_error = no_error;
4094           abort();              /* FIXME */
4095         }
4096       obj_som_copyright_hdr (abfd)->header_id.type = COPYRIGHT_AUX_ID;
4097       obj_som_copyright_hdr (abfd)->header_id.length = len + pad;
4098       obj_som_copyright_hdr (abfd)->header_id.length += sizeof (int);
4099       obj_som_copyright_hdr (abfd)->string_length = len;
4100       strcpy (obj_som_copyright_hdr (abfd)->copyright, string);
4101     }
4102   else
4103     abort ();
4104 }
4105
4106 static boolean
4107 som_set_section_contents (abfd, section, location, offset, count)
4108      bfd *abfd;
4109      sec_ptr section;
4110      PTR location;
4111      file_ptr offset;
4112      bfd_size_type count;
4113 {
4114   if (abfd->output_has_begun == false)
4115     {
4116       /* Set up fixed parts of the file, space, and subspace headers.
4117          Notify the world that output has begun.  */
4118       som_prep_headers (abfd);
4119       abfd->output_has_begun = true;
4120       /* Start writing the object file.  This include all the string
4121          tables, fixup streams, and other portions of the object file.  */
4122       som_begin_writing (abfd);
4123     }
4124
4125   /* Only write subspaces which have "real" contents (eg. the contents
4126      are not generated at run time by the OS).  */
4127   if (som_section_data (section)->is_subspace != 1
4128       || ((section->flags & (SEC_LOAD | SEC_DEBUGGING)) == 0))
4129     return true;
4130
4131   /* Seek to the proper offset within the object file and write the
4132      data.  */
4133   offset += som_section_data (section)->subspace_dict.file_loc_init_value; 
4134   if (bfd_seek (abfd, offset, SEEK_SET) == -1)
4135     {
4136       bfd_error = system_call_error;
4137       return false;
4138     }
4139
4140   if (bfd_write ((PTR) location, 1, count, abfd) != count)
4141     {
4142       bfd_error = system_call_error;
4143       return false;
4144     }
4145   return true;
4146 }
4147
4148 static boolean
4149 som_set_arch_mach (abfd, arch, machine)
4150      bfd *abfd;
4151      enum bfd_architecture arch;
4152      unsigned long machine;
4153 {
4154   /* Allow any architecture to be supported by the SOM backend */
4155   return bfd_default_set_arch_mach (abfd, arch, machine);
4156 }
4157
4158 static boolean
4159 som_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
4160                         functionname_ptr, line_ptr)
4161      bfd *abfd;
4162      asection *section;
4163      asymbol **symbols;
4164      bfd_vma offset;
4165      CONST char **filename_ptr;
4166      CONST char **functionname_ptr;
4167      unsigned int *line_ptr;
4168 {
4169   fprintf (stderr, "som_find_nearest_line unimplemented\n");
4170   fflush (stderr);
4171   abort ();
4172   return (false);
4173 }
4174
4175 static int
4176 som_sizeof_headers (abfd, reloc)
4177      bfd *abfd;
4178      boolean reloc;
4179 {
4180   fprintf (stderr, "som_sizeof_headers unimplemented\n");
4181   fflush (stderr);
4182   abort ();
4183   return (0);
4184 }
4185
4186 /* Return the single-character symbol type corresponding to
4187    SOM section S, or '?' for an unknown SOM section.  */
4188
4189 static char
4190 som_section_type (s)
4191      const char *s;
4192 {
4193   const struct section_to_type *t;
4194
4195   for (t = &stt[0]; t->section; t++)
4196     if (!strcmp (s, t->section))
4197       return t->type;
4198   return '?';
4199 }
4200
4201 static int
4202 som_decode_symclass (symbol)
4203      asymbol *symbol;
4204 {
4205   char c;
4206
4207   if (bfd_is_com_section (symbol->section))
4208     return 'C';
4209   if (symbol->section == &bfd_und_section)
4210     return 'U';
4211   if (symbol->section == &bfd_ind_section)
4212     return 'I';
4213   if (!(symbol->flags & (BSF_GLOBAL|BSF_LOCAL)))
4214     return '?';
4215
4216   if (symbol->section == &bfd_abs_section)
4217     c = 'a';
4218   else if (symbol->section)
4219     c = som_section_type (symbol->section->name);
4220   else
4221     return '?';
4222   if (symbol->flags & BSF_GLOBAL)
4223     c = toupper (c);
4224   return c;
4225 }
4226
4227 /* Return information about SOM symbol SYMBOL in RET.  */
4228
4229 static void
4230 som_get_symbol_info (ignore_abfd, symbol, ret)
4231      bfd *ignore_abfd;
4232      asymbol *symbol;
4233      symbol_info *ret;
4234 {
4235   ret->type = som_decode_symclass (symbol);
4236   if (ret->type != 'U')
4237     ret->value = symbol->value+symbol->section->vma;
4238   else
4239     ret->value = 0;
4240   ret->name = symbol->name;
4241 }
4242
4243 /* Count the number of symbols in the archive symbol table.  Necessary
4244    so that we can allocate space for all the carsyms at once.  */
4245
4246 static boolean
4247 som_bfd_count_ar_symbols (abfd, lst_header, count)
4248      bfd *abfd;
4249      struct lst_header *lst_header;
4250      symindex *count;
4251 {
4252   unsigned int i;
4253   unsigned int hash_table[lst_header->hash_size];
4254   file_ptr lst_filepos = bfd_tell (abfd) - sizeof (struct lst_header);
4255
4256   /* Don't forget to initialize the counter!  */
4257   *count = 0;
4258
4259   /* Read in the hash table.  The has table is an array of 32bit file offsets
4260      which point to the hash chains.  */
4261   if (bfd_read ((PTR) hash_table, lst_header->hash_size, 4, abfd)
4262       != lst_header->hash_size * 4)
4263     {
4264       bfd_error = system_call_error;
4265       return false;
4266     }
4267
4268   /* Walk each chain counting the number of symbols found on that particular
4269      chain.  */
4270   for (i = 0; i < lst_header->hash_size; i++)
4271     {
4272       struct lst_symbol_record lst_symbol;
4273
4274       /* An empty chain has zero as it's file offset.  */
4275       if (hash_table[i] == 0)
4276         continue;
4277
4278       /* Seek to the first symbol in this hash chain.  */
4279       if (bfd_seek (abfd, lst_filepos + hash_table[i], SEEK_SET) < 0)
4280         {
4281           bfd_error = system_call_error;
4282           return false;
4283         }
4284
4285       /* Read in this symbol and update the counter.  */
4286       if (bfd_read ((PTR) & lst_symbol, 1, sizeof (lst_symbol), abfd)
4287           != sizeof (lst_symbol))
4288         {
4289           bfd_error = system_call_error;
4290           return false;
4291         }
4292       (*count)++;
4293
4294       /* Now iterate through the rest of the symbols on this chain.  */
4295       while (lst_symbol.next_entry)
4296         {
4297
4298           /* Seek to the next symbol.  */
4299           if (bfd_seek (abfd, lst_filepos + lst_symbol.next_entry, SEEK_SET)
4300               < 0)
4301             {
4302               bfd_error = system_call_error;
4303               return false;
4304             }
4305
4306           /* Read the symbol in and update the counter.  */
4307           if (bfd_read ((PTR) & lst_symbol, 1, sizeof (lst_symbol), abfd)
4308               != sizeof (lst_symbol))
4309             {
4310               bfd_error = system_call_error;
4311               return false;
4312             }
4313           (*count)++;
4314         }
4315     }
4316   return true;
4317 }
4318
4319 /* Fill in the canonical archive symbols (SYMS) from the archive described
4320    by ABFD and LST_HEADER.  */
4321
4322 static boolean
4323 som_bfd_fill_in_ar_symbols (abfd, lst_header, syms)
4324      bfd *abfd;
4325      struct lst_header *lst_header;
4326      carsym **syms;
4327 {
4328   unsigned int i, len;
4329   carsym *set = syms[0];
4330   unsigned int hash_table[lst_header->hash_size];
4331   struct som_entry som_dict[lst_header->module_count];
4332   file_ptr lst_filepos = bfd_tell (abfd) - sizeof (struct lst_header);
4333
4334   /* Read in the hash table.  The has table is an array of 32bit file offsets
4335      which point to the hash chains.  */
4336   if (bfd_read ((PTR) hash_table, lst_header->hash_size, 4, abfd)
4337       != lst_header->hash_size * 4)
4338     {
4339       bfd_error = system_call_error;
4340       return false;
4341     }
4342
4343   /* Seek to and read in the SOM dictionary.  We will need this to fill
4344      in the carsym's filepos field.  */
4345   if (bfd_seek (abfd, lst_filepos + lst_header->dir_loc, SEEK_SET) < 0)
4346     {
4347       bfd_error = system_call_error;
4348       return false;
4349     }
4350
4351   if (bfd_read ((PTR) som_dict, lst_header->module_count, 
4352                 sizeof (struct som_entry), abfd)
4353       != lst_header->module_count * sizeof (struct som_entry))
4354     {
4355       bfd_error = system_call_error;
4356       return false;
4357     }
4358
4359   /* Walk each chain filling in the carsyms as we go along.  */
4360   for (i = 0; i < lst_header->hash_size; i++)
4361     {
4362       struct lst_symbol_record lst_symbol;
4363
4364       /* An empty chain has zero as it's file offset.  */
4365       if (hash_table[i] == 0)
4366         continue;
4367
4368       /* Seek to and read the first symbol on the chain.  */
4369       if (bfd_seek (abfd, lst_filepos + hash_table[i], SEEK_SET) < 0)
4370         {
4371           bfd_error = system_call_error;
4372           return false;
4373         }
4374
4375       if (bfd_read ((PTR) & lst_symbol, 1, sizeof (lst_symbol), abfd)
4376           != sizeof (lst_symbol))
4377         {
4378           bfd_error = system_call_error;
4379           return false;
4380         }
4381
4382       /* Get the name of the symbol, first get the length which is stored
4383          as a 32bit integer just before the symbol.
4384
4385          One might ask why we don't just read in the entire string table
4386          and index into it.  Well, according to the SOM ABI the string
4387          index can point *anywhere* in the archive to save space, so just
4388          using the string table would not be safe.  */
4389       if (bfd_seek (abfd, lst_filepos + lst_header->string_loc
4390                             + lst_symbol.name.n_strx - 4, SEEK_SET) < 0)
4391         {
4392           bfd_error = system_call_error;
4393           return false;
4394         }
4395
4396       if (bfd_read (&len, 1, 4, abfd) != 4)
4397         {
4398           bfd_error = system_call_error;
4399           return false;
4400         }
4401
4402       /* Allocate space for the name and null terminate it too.  */
4403       set->name = bfd_zalloc (abfd, len + 1);
4404       if (!set->name)
4405         {
4406           bfd_error = no_memory;
4407           return false;
4408         }
4409       if (bfd_read (set->name, 1, len, abfd) != len)
4410         {
4411           bfd_error = system_call_error;
4412           return false;
4413         }
4414       set->name[len] = 0;
4415
4416       /* Fill in the file offset.  Note that the "location" field points
4417          to the SOM itself, not the ar_hdr in front of it.  */
4418       set->file_offset = som_dict[lst_symbol.som_index].location
4419                           - sizeof (struct ar_hdr);
4420
4421       /* Go to the next symbol.  */
4422       set++;
4423
4424       /* Iterate through the rest of the chain.  */
4425       while (lst_symbol.next_entry)
4426         {
4427           /* Seek to the next symbol and read it in.  */
4428           if (bfd_seek (abfd, lst_filepos + lst_symbol.next_entry, SEEK_SET)
4429               < 0)
4430             {
4431               bfd_error = system_call_error;
4432               return false;
4433             }
4434
4435           if (bfd_read ((PTR) & lst_symbol, 1, sizeof (lst_symbol), abfd)
4436               != sizeof (lst_symbol))
4437             {
4438               bfd_error = system_call_error;
4439               return false;
4440             }
4441
4442           /* Seek to the name length & string and read them in.  */
4443           if (bfd_seek (abfd, lst_filepos + lst_header->string_loc 
4444                                 + lst_symbol.name.n_strx - 4, SEEK_SET) < 0)
4445             {
4446               bfd_error = system_call_error;
4447               return false;
4448             }
4449
4450           if (bfd_read (&len, 1, 4, abfd) != 4)
4451             {
4452               bfd_error = system_call_error;
4453               return false;
4454             }
4455
4456           /* Allocate space for the name and null terminate it too.  */
4457           set->name = bfd_zalloc (abfd, len + 1);
4458           if (!set->name)
4459             {
4460               bfd_error = no_memory;
4461               return false;
4462             }
4463           if (bfd_read (set->name, 1, len, abfd) != len)
4464             {
4465               bfd_error = system_call_error;
4466               return false;
4467             }
4468           set->name[len] = 0;
4469
4470           /* Fill in the file offset.  Note that the "location" field points
4471              to the SOM itself, not the ar_hdr in front of it.  */
4472           set->file_offset = som_dict[lst_symbol.som_index].location
4473                                - sizeof (struct ar_hdr);
4474
4475           /* Go on to the next symbol.  */
4476           set++;
4477         }
4478     }
4479   /* If we haven't died by now, then we successfully read the entire 
4480      archive symbol table.  */
4481   return true;
4482 }
4483
4484 /* Read in the LST from the archive.  */
4485 static boolean
4486 som_slurp_armap (abfd)
4487      bfd *abfd;
4488 {
4489   struct lst_header lst_header;
4490   struct ar_hdr ar_header;
4491   unsigned int parsed_size;
4492   struct artdata *ardata = bfd_ardata (abfd);
4493   char nextname[17];
4494   int i = bfd_read ((PTR) nextname, 1, 16, abfd);
4495
4496   /* Special cases.  */
4497   if (i == 0)
4498     return true;
4499   if (i != 16)
4500     return false;
4501
4502   if (bfd_seek (abfd, (file_ptr) - 16, SEEK_CUR) < 0)
4503     {
4504       bfd_error = system_call_error;
4505       return false;
4506     }
4507
4508   /* For archives without .o files there is no symbol table.  */
4509   if (strncmp (nextname, "/               ", 16))
4510     {
4511       bfd_has_map (abfd) = false;
4512       return true;
4513     }
4514
4515   /* Read in and sanity check the archive header.  */
4516   if (bfd_read ((PTR) &ar_header, 1, sizeof (struct ar_hdr), abfd)
4517       != sizeof (struct ar_hdr))
4518     {
4519       bfd_error = system_call_error;
4520       return false;
4521     }
4522
4523   if (strncmp (ar_header.ar_fmag, ARFMAG, 2))
4524     {
4525       bfd_error = malformed_archive;
4526       return NULL;
4527     }
4528
4529   /* How big is the archive symbol table entry?  */
4530   errno = 0;
4531   parsed_size = strtol (ar_header.ar_size, NULL, 10);
4532   if (errno != 0)
4533     {
4534       bfd_error = malformed_archive;
4535       return NULL;
4536     }
4537
4538   /* Save off the file offset of the first real user data.  */
4539   ardata->first_file_filepos = bfd_tell (abfd) + parsed_size;
4540
4541   /* Read in the library symbol table.  We'll make heavy use of this
4542      in just a minute.  */
4543   if (bfd_read ((PTR) & lst_header, 1, sizeof (struct lst_header), abfd)
4544       != sizeof (struct lst_header))
4545     {
4546       bfd_error = system_call_error;
4547       return false;
4548     }
4549
4550   /* Sanity check.  */
4551   if (lst_header.a_magic != LIBMAGIC)
4552     {
4553       bfd_error = malformed_archive;
4554       return NULL;
4555     }
4556
4557   /* Count the number of symbols in the library symbol table.  */
4558   if (som_bfd_count_ar_symbols (abfd, &lst_header, &ardata->symdef_count)
4559       == false)
4560     return false;
4561
4562   /* Get back to the start of the library symbol table.  */
4563   if (bfd_seek (abfd, ardata->first_file_filepos - parsed_size 
4564                         + sizeof (struct lst_header), SEEK_SET) < 0)
4565     {
4566       bfd_error = system_call_error;
4567       return false;
4568     }
4569
4570   /* Initializae the cache and allocate space for the library symbols.  */
4571   ardata->cache = 0;
4572   ardata->symdefs = (carsym *) bfd_alloc (abfd,
4573                                           (ardata->symdef_count
4574                                            * sizeof (carsym)));
4575   if (!ardata->symdefs)
4576     {
4577       bfd_error = no_memory;
4578       return false;
4579     }
4580
4581   /* Now fill in the canonical archive symbols.  */
4582   if (som_bfd_fill_in_ar_symbols (abfd, &lst_header, &ardata->symdefs)
4583       == false)
4584     return false;
4585
4586   /* Notify the generic archive code that we have a symbol map.  */
4587   bfd_has_map (abfd) = true;
4588   return true;
4589 }
4590
4591 /* Begin preparing to write a SOM library symbol table.
4592
4593    As part of the prep work we need to determine the number of symbols
4594    and the size of the associated string section.  */
4595
4596 static boolean
4597 som_bfd_prep_for_ar_write (abfd, num_syms, stringsize)
4598      bfd *abfd;
4599      unsigned int *num_syms, *stringsize;
4600 {
4601   bfd *curr_bfd = abfd->archive_head;
4602
4603   /* Some initialization.  */
4604   *num_syms = 0;
4605   *stringsize = 0;
4606
4607   /* Iterate over each BFD within this archive.  */
4608   while (curr_bfd != NULL)
4609     {
4610       unsigned int curr_count, i;
4611       som_symbol_type *sym;
4612
4613       /* Make sure the symbol table has been read, then snag a pointer
4614          to it.  It's a little slimey to grab the symbols via obj_som_symtab,
4615          but doing so avoids allocating lots of extra memory.  */
4616       if (som_slurp_symbol_table (curr_bfd) == false)
4617         return false;
4618
4619       sym = obj_som_symtab (curr_bfd);
4620       curr_count = bfd_get_symcount (curr_bfd);
4621
4622       /* Examine each symbol to determine if it belongs in the
4623          library symbol table.  */
4624       for (i = 0; i < curr_count; i++, sym++)
4625         {
4626           struct som_misc_symbol_info info;
4627
4628           /* Derive SOM information from the BFD symbol.  */
4629           som_bfd_derive_misc_symbol_info (curr_bfd, &sym->symbol, &info);
4630
4631           /* Should we include this symbol?  */
4632           if (info.symbol_type == ST_NULL
4633               || info.symbol_type == ST_SYM_EXT
4634               || info.symbol_type == ST_ARG_EXT)
4635             continue;
4636
4637           /* Only global symbols and unsatisfied commons.  */
4638           if (info.symbol_scope != SS_UNIVERSAL
4639               && info.symbol_type != ST_STORAGE)
4640             continue;
4641
4642           /* Do no include undefined symbols.  */
4643           if (sym->symbol.section == &bfd_und_section)
4644             continue;
4645
4646           /* Bump the various counters, being careful to honor
4647              alignment considerations in the string table.  */
4648           (*num_syms)++;
4649           *stringsize = *stringsize + strlen (sym->symbol.name) + 5;
4650           while (*stringsize % 4)
4651             (*stringsize)++;
4652         }
4653
4654       curr_bfd = curr_bfd->next;
4655     }
4656   return true;
4657 }
4658
4659 /* Hash a symbol name based on the hashing algorithm presented in the
4660    SOM ABI.  */
4661 static unsigned int
4662 som_bfd_ar_symbol_hash (symbol)
4663      asymbol *symbol;
4664 {
4665   unsigned int len = strlen (symbol->name);
4666
4667   /* Names with length 1 are special.  */
4668   if (len == 1)
4669     return 0x1000100 | (symbol->name[0] << 16) | symbol->name[0];
4670
4671   return ((len & 0x7f) << 24) | (symbol->name[1] << 16)
4672           | (symbol->name[len-2] << 8) | symbol->name[len-1];
4673 }
4674
4675 /* Do the bulk of the work required to write the SOM library
4676    symbol table.  */
4677    
4678 static boolean
4679 som_bfd_ar_write_symbol_stuff (abfd, nsyms, string_size, lst)
4680      bfd *abfd;
4681      unsigned int nsyms, string_size;
4682      struct lst_header lst;
4683 {
4684   file_ptr lst_filepos;
4685   char *strings, *p;
4686   struct lst_symbol_record *lst_syms, *curr_lst_sym;
4687   bfd *curr_bfd = abfd->archive_head;
4688   unsigned int hash_table[lst.hash_size];
4689   struct som_entry som_dict[lst.module_count];
4690   struct lst_symbol_record *last_hash_entry[lst.hash_size];
4691   unsigned int curr_som_offset, som_index;
4692
4693   /* Lots of fields are file positions relative to the start
4694      of the lst record.  So save its location.  */
4695   lst_filepos = bfd_tell (abfd) - sizeof (struct lst_header);
4696
4697   /* Some initialization.  */
4698   memset (hash_table, 0, 4 * lst.hash_size);
4699   memset (som_dict, 0, lst.module_count * sizeof (struct som_entry));
4700   memset (last_hash_entry, 0,   
4701           lst.hash_size * sizeof (struct lst_symbol_record *));
4702
4703   /* Symbols have som_index fields, so we have to keep track of the
4704      index of each SOM in the archive.
4705
4706      The SOM dictionary has (among other things) the absolute file
4707      position for the SOM which a particular dictionary entry
4708      describes.  We have to compute that information as we iterate
4709      through the SOMs/symbols.  */
4710   som_index = 0;
4711   curr_som_offset = 8 + 2 * sizeof (struct ar_hdr) + lst.file_end;
4712
4713   /* FIXME should be done with buffers just like everything else... */
4714   lst_syms = alloca (nsyms * sizeof (struct lst_symbol_record));
4715   strings = alloca (string_size);
4716   p = strings;
4717   curr_lst_sym = lst_syms;
4718
4719
4720   while (curr_bfd != NULL)
4721     {
4722       unsigned int curr_count, i;
4723       som_symbol_type *sym;
4724
4725       /* Make sure the symbol table has been read, then snag a pointer
4726          to it.  It's a little slimey to grab the symbols via obj_som_symtab,
4727          but doing so avoids allocating lots of extra memory.  */
4728       if (som_slurp_symbol_table (curr_bfd) == false)
4729         return false;
4730
4731       sym = obj_som_symtab (curr_bfd);
4732       curr_count = bfd_get_symcount (curr_bfd);
4733
4734       for (i = 0; i < curr_count; i++, sym++)
4735         {
4736           struct som_misc_symbol_info info;
4737
4738           /* Derive SOM information from the BFD symbol.  */
4739           som_bfd_derive_misc_symbol_info (curr_bfd, &sym->symbol, &info);
4740
4741           /* Should we include this symbol?  */
4742           if (info.symbol_type == ST_NULL
4743               || info.symbol_type == ST_SYM_EXT
4744               || info.symbol_type == ST_ARG_EXT)
4745             continue;
4746
4747           /* Only global symbols and unsatisfied commons.  */
4748           if (info.symbol_scope != SS_UNIVERSAL
4749               && info.symbol_type != ST_STORAGE)
4750             continue;
4751
4752           /* Do no include undefined symbols.  */
4753           if (sym->symbol.section == &bfd_und_section)
4754             continue;
4755
4756           /* If this is the first symbol from this SOM, then update
4757              the SOM dictionary too.  */
4758           if (som_dict[som_index].location == 0)
4759             {
4760               som_dict[som_index].location = curr_som_offset;
4761               som_dict[som_index].length = arelt_size (curr_bfd);
4762             }
4763
4764           /* Fill in the lst symbol record.  */
4765           curr_lst_sym->hidden = 0;
4766           curr_lst_sym->secondary_def = 0;
4767           curr_lst_sym->symbol_type = info.symbol_type;
4768           curr_lst_sym->symbol_scope = info.symbol_scope;
4769           curr_lst_sym->check_level = 0;
4770           curr_lst_sym->must_qualify = 0;
4771           curr_lst_sym->initially_frozen = 0;
4772           curr_lst_sym->memory_resident = 0;
4773           curr_lst_sym->is_common = (sym->symbol.section == &bfd_com_section);
4774           curr_lst_sym->dup_common = 0;
4775           curr_lst_sym->xleast = 0;
4776           curr_lst_sym->arg_reloc = info.arg_reloc;
4777           curr_lst_sym->name.n_strx = p - strings + 4;
4778           curr_lst_sym->qualifier_name.n_strx = 0;
4779           curr_lst_sym->symbol_info = info.symbol_info;
4780           curr_lst_sym->symbol_value = info.symbol_value;
4781           curr_lst_sym->symbol_descriptor = 0;
4782           curr_lst_sym->reserved = 0;
4783           curr_lst_sym->som_index = som_index;
4784           curr_lst_sym->symbol_key = som_bfd_ar_symbol_hash (&sym->symbol);
4785           curr_lst_sym->next_entry = 0;
4786
4787           /* Insert into the hash table.  */
4788           if (hash_table[curr_lst_sym->symbol_key % lst.hash_size])
4789             {
4790               struct lst_symbol_record *tmp;
4791
4792               /* There is already something at the head of this hash chain,
4793                  so tack this symbol onto the end of the chain.  */
4794               tmp = last_hash_entry[curr_lst_sym->symbol_key % lst.hash_size];
4795               tmp->next_entry
4796                 = (curr_lst_sym - lst_syms) * sizeof (struct lst_symbol_record)
4797                   + lst.hash_size * 4 
4798                   + lst.module_count * sizeof (struct som_entry)
4799                   + sizeof (struct lst_header);
4800             }
4801           else
4802             {
4803               /* First entry in this hash chain.  */
4804               hash_table[curr_lst_sym->symbol_key % lst.hash_size]
4805                 = (curr_lst_sym - lst_syms) * sizeof (struct lst_symbol_record)
4806                   + lst.hash_size * 4 
4807                   + lst.module_count * sizeof (struct som_entry)
4808                   + sizeof (struct lst_header);
4809             }
4810
4811           /* Keep track of the last symbol we added to this chain so we can
4812              easily update its next_entry pointer.  */
4813           last_hash_entry[curr_lst_sym->symbol_key % lst.hash_size]
4814             = curr_lst_sym;
4815
4816
4817           /* Update the string table.  */
4818           bfd_put_32 (abfd, strlen (sym->symbol.name), p);
4819           p += 4;
4820           strcpy (p, sym->symbol.name);
4821           p += strlen (sym->symbol.name) + 1;
4822           while ((int)p % 4)
4823             {
4824               bfd_put_8 (abfd, 0, p);
4825               p++;
4826             }
4827
4828           /* Head to the next symbol.  */
4829           curr_lst_sym++;
4830         }
4831
4832       /* Keep track of where each SOM will finally reside; then look
4833          at the next BFD.  */
4834       curr_som_offset += arelt_size (curr_bfd) + sizeof (struct ar_hdr);
4835       curr_bfd = curr_bfd->next;
4836       som_index++;
4837     }
4838
4839   /* Now scribble out the hash table.  */
4840   if (bfd_write ((PTR) hash_table, lst.hash_size, 4, abfd)
4841       != lst.hash_size * 4)
4842     {
4843       bfd_error = system_call_error;
4844       return false;
4845     }
4846
4847   /* Then the SOM dictionary.  */
4848   if (bfd_write ((PTR) som_dict, lst.module_count,
4849                  sizeof (struct som_entry), abfd)
4850       != lst.module_count * sizeof (struct som_entry))
4851     {
4852       bfd_error = system_call_error;
4853       return false;
4854     }
4855
4856   /* The library symbols.  */
4857   if (bfd_write ((PTR) lst_syms, nsyms, sizeof (struct lst_symbol_record), abfd)
4858       != nsyms * sizeof (struct lst_symbol_record))
4859     {
4860       bfd_error = system_call_error;
4861       return false;
4862     }
4863
4864   /* And finally the strings.  */
4865   if (bfd_write ((PTR) strings, string_size, 1, abfd) != string_size)
4866     {
4867       bfd_error = system_call_error;
4868       return false;
4869     }
4870
4871   return true;
4872 }
4873
4874 /* Write out the LST for the archive.
4875
4876    You'll never believe this is really how armaps are handled in SOM...  */
4877
4878 static boolean
4879 som_write_armap (abfd)
4880      bfd *abfd;
4881 {
4882   bfd *curr_bfd;
4883   struct stat statbuf;
4884   unsigned int i, lst_size, nsyms, stringsize;
4885   struct ar_hdr hdr;
4886   struct lst_header lst;
4887   int *p;
4888  
4889   /* We'll use this for the archive's date and mode later.  */
4890   if (stat (abfd->filename, &statbuf) != 0)
4891     {
4892       bfd_error = system_call_error;
4893       return false;
4894     }
4895   /* Fudge factor.  */
4896   bfd_ardata (abfd)->armap_timestamp = statbuf.st_mtime + 60;
4897
4898   /* Account for the lst header first.  */
4899   lst_size = sizeof (struct lst_header);
4900
4901   /* Start building the LST header.  */
4902   lst.system_id = HP9000S800_ID;
4903   lst.a_magic = LIBMAGIC;
4904   lst.version_id = VERSION_ID;
4905   lst.file_time.secs = 0;
4906   lst.file_time.nanosecs = 0;
4907
4908   lst.hash_loc = lst_size;
4909   lst.hash_size = SOM_LST_HASH_SIZE;
4910
4911   /* Hash table is a SOM_LST_HASH_SIZE 32bit offsets.  */
4912   lst_size += 4 * SOM_LST_HASH_SIZE;
4913
4914   /* We need to count the number of SOMs in this archive.  */
4915   curr_bfd = abfd->archive_head;
4916   lst.module_count = 0;
4917   while (curr_bfd != NULL)
4918     {
4919       lst.module_count++;
4920       curr_bfd = curr_bfd->next;
4921     }
4922   lst.module_limit = lst.module_count;
4923   lst.dir_loc = lst_size;
4924   lst_size += sizeof (struct som_entry) * lst.module_count;
4925
4926   /* We don't support import/export tables, auxiliary headers,
4927      or free lists yet.  Make the linker work a little harder
4928      to make our life easier.  */
4929
4930   lst.export_loc = 0;
4931   lst.export_count = 0;
4932   lst.import_loc = 0;
4933   lst.aux_loc = 0;
4934   lst.aux_size = 0;
4935
4936   /* Count how many symbols we will have on the hash chains and the
4937      size of the associated string table.  */
4938   if (som_bfd_prep_for_ar_write (abfd, &nsyms, &stringsize) == false)
4939     return false;
4940
4941   lst_size += sizeof (struct lst_symbol_record) * nsyms;
4942
4943   /* For the string table.  One day we might actually use this info
4944      to avoid small seeks/reads when reading archives.  */
4945   lst.string_loc = lst_size;
4946   lst.string_size = stringsize;
4947   lst_size += stringsize;
4948
4949   /* SOM ABI says this must be zero.  */
4950   lst.free_list = 0;
4951
4952   lst.file_end = lst_size;
4953
4954   /* Compute the checksum.  Must happen after the entire lst header
4955      has filled in.  */
4956   p = (int *)&lst;
4957   for (i = 0; i < sizeof (struct lst_header)/sizeof (int) - 1; i++)
4958     lst.checksum ^= *p++;
4959
4960   sprintf (hdr.ar_name, "/               ");
4961   sprintf (hdr.ar_date, "%ld", bfd_ardata (abfd)->armap_timestamp);
4962   sprintf (hdr.ar_uid, "%d", getuid ());
4963   sprintf (hdr.ar_gid, "%d", getgid ());
4964   sprintf (hdr.ar_mode, "%-8o", (unsigned int) statbuf.st_mode);
4965   sprintf (hdr.ar_size, "%-10d", (int) lst_size);
4966   hdr.ar_fmag[0] = '`';
4967   hdr.ar_fmag[1] = '\012';
4968
4969   /* Turn any nulls into spaces.  */
4970   for (i = 0; i < sizeof (struct ar_hdr); i++)
4971     if (((char *) (&hdr))[i] == '\0')
4972       (((char *) (&hdr))[i]) = ' ';
4973
4974   /* Scribble out the ar header.  */
4975   if (bfd_write ((PTR) &hdr, 1, sizeof (struct ar_hdr), abfd)
4976       != sizeof (struct ar_hdr))
4977     {
4978       bfd_error = system_call_error;
4979       return false;
4980     }
4981
4982   /* Now scribble out the lst header.  */
4983   if (bfd_write ((PTR) &lst, 1, sizeof (struct lst_header), abfd)
4984       != sizeof (struct lst_header))
4985     {
4986       bfd_error = system_call_error;
4987       return false;
4988     }
4989
4990   /* Build and write the armap.  */
4991   if (som_bfd_ar_write_symbol_stuff (abfd, nsyms, stringsize, lst) == false)
4992     return false;
4993   
4994   /* Done.  */
4995   return true;
4996 }
4997
4998 /* Apparently the extened names are never used, even though they appear
4999    in the SOM ABI.  Hmmm.  */
5000 static boolean
5001 som_slurp_extended_name_table (abfd)
5002      bfd *abfd;
5003 {
5004   bfd_ardata (abfd)->extended_names = NULL;
5005   return true;
5006 }
5007
5008 /* End of miscellaneous support functions. */
5009
5010 #define som_bfd_debug_info_start        bfd_void
5011 #define som_bfd_debug_info_end          bfd_void
5012 #define som_bfd_debug_info_accumulate   (PROTO(void,(*),(bfd*, struct sec *))) bfd_void
5013
5014 #define som_openr_next_archived_file    bfd_generic_openr_next_archived_file
5015 #define som_generic_stat_arch_elt       bfd_generic_stat_arch_elt
5016 #define som_truncate_arname             bfd_bsd_truncate_arname
5017
5018 #define som_get_lineno                   (struct lineno_cache_entry *(*)())bfd_nullvoidptr
5019 #define som_close_and_cleanup              bfd_generic_close_and_cleanup
5020 #define som_get_section_contents          bfd_generic_get_section_contents
5021
5022 #define som_bfd_get_relocated_section_contents \
5023  bfd_generic_get_relocated_section_contents
5024 #define som_bfd_relax_section bfd_generic_relax_section
5025 #define som_bfd_make_debug_symbol \
5026   ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr)
5027 #define som_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
5028 #define som_bfd_link_add_symbols _bfd_generic_link_add_symbols
5029 #define som_bfd_final_link _bfd_generic_final_link
5030
5031 /* Core file support is in the hpux-core backend.  */
5032 #define som_core_file_failing_command   _bfd_dummy_core_file_failing_command
5033 #define som_core_file_failing_signal    _bfd_dummy_core_file_failing_signal
5034 #define som_core_file_matches_executable_p      _bfd_dummy_core_file_matches_executable_p
5035
5036 bfd_target som_vec =
5037 {
5038   "som",                        /* name */
5039   bfd_target_som_flavour,
5040   true,                         /* target byte order */
5041   true,                         /* target headers byte order */
5042   (HAS_RELOC | EXEC_P |         /* object flags */
5043    HAS_LINENO | HAS_DEBUG |
5044    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
5045   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
5046    | SEC_ALLOC | SEC_LOAD | SEC_RELOC),         /* section flags */
5047
5048 /* leading_symbol_char: is the first char of a user symbol
5049    predictable, and if so what is it */
5050   0,
5051   '/',                          /* ar_pad_char */
5052   16,                           /* ar_max_namelen */
5053   3,                            /* minimum alignment */
5054   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
5055   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
5056   bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* data */
5057   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
5058   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
5059   bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* hdrs */
5060   {_bfd_dummy_target,
5061    som_object_p,                /* bfd_check_format */
5062    bfd_generic_archive_p,
5063    _bfd_dummy_target
5064   },
5065   {
5066     bfd_false,
5067     som_mkobject,
5068     _bfd_generic_mkarchive,
5069     bfd_false
5070   },
5071   {
5072     bfd_false,
5073     som_write_object_contents,
5074     _bfd_write_archive_contents,
5075     bfd_false,
5076   },
5077 #undef som
5078   JUMP_TABLE (som),
5079   (PTR) 0
5080 };
5081
5082 #endif /* HOST_HPPAHPUX || HOST_HPPABSD || HOST_HPPAOSF */