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