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