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