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