]> Git Repo - binutils.git/blob - bfd/som.c
* objcopy.c (strip_main, copy_main): Add missing 'break' in switch.
[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 ([email protected]).
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 (!bcmp (p, queue[0].reloc, size)
1025       && size == queue[0].size)
1026     return 0;
1027   if (!bcmp (p, queue[1].reloc, size)
1028       && size == queue[1].size)
1029     return 1;
1030   if (!bcmp (p, queue[2].reloc, size)
1031       && size == queue[2].size)
1032     return 2;
1033   if (!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
1351   /* The field selector may require additional relocations to be 
1352      generated.  It's impossible to know at this moment if additional
1353      relocations will be needed, so we make them.  The code to actually
1354      write the relocation/fixup stream is responsible for removing
1355      any redundant relocations.  */
1356   switch (field)
1357     {
1358       case e_fsel:
1359       case e_psel:
1360       case e_lpsel:
1361       case e_rpsel:
1362         final_types[0] = final_type;
1363         final_types[1] = NULL;
1364         final_types[2] = NULL;
1365         *final_type = base_type;
1366         break;
1367
1368       case e_tsel:
1369       case e_ltsel:
1370       case e_rtsel:
1371         final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
1372         if (field == e_tsel)
1373           *final_types[0] = R_FSEL;
1374         else if (field == e_ltsel)
1375           *final_types[0] = R_LSEL;
1376         else
1377           *final_types[0] = R_RSEL;
1378         final_types[1] = final_type;
1379         final_types[2] = NULL;
1380         *final_type = base_type;
1381         break;
1382
1383       case e_lssel:
1384       case e_rssel:
1385         final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
1386         *final_types[0] = R_S_MODE;
1387         final_types[1] = final_type;
1388         final_types[2] = NULL;
1389         *final_type = base_type;
1390         break;
1391
1392       case e_lsel:
1393       case e_rsel:
1394         final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
1395         *final_types[0] = R_N_MODE;
1396         final_types[1] = final_type;
1397         final_types[2] = NULL;
1398         *final_type = base_type;
1399         break;
1400
1401       case e_ldsel:
1402       case e_rdsel:
1403         final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
1404         *final_types[0] = R_D_MODE;
1405         final_types[1] = final_type;
1406         final_types[2] = NULL;
1407         *final_type = base_type;
1408         break;
1409
1410       case e_lrsel:
1411       case e_rrsel:
1412         final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
1413         *final_types[0] = R_R_MODE;
1414         final_types[1] = final_type;
1415         final_types[2] = NULL;
1416         *final_type = base_type;
1417         break;
1418     }
1419   
1420   switch (base_type)
1421     {
1422     case R_HPPA:
1423       /* PLABELs get their own relocation type.  */
1424       if (field == e_psel
1425           || field == e_lpsel
1426           || field == e_rpsel)
1427         {
1428           /* A PLABEL relocation that has a size of 32 bits must
1429              be a R_DATA_PLABEL.  All others are R_CODE_PLABELs.  */
1430           if (format == 32)
1431             *final_type = R_DATA_PLABEL;
1432           else
1433             *final_type = R_CODE_PLABEL;
1434         }
1435       /* PIC stuff.  */
1436       else if (field == e_tsel
1437           || field == e_ltsel
1438           || field == e_rtsel)
1439         *final_type = R_DLT_REL;
1440       /* A relocation in the data space is always a full 32bits.  */
1441       else if (format == 32)
1442         *final_type = R_DATA_ONE_SYMBOL;
1443
1444       break;
1445
1446     case R_HPPA_GOTOFF:
1447       /* More PLABEL special cases.  */
1448       if (field == e_psel
1449           || field == e_lpsel
1450           || field == e_rpsel)
1451         *final_type = R_DATA_PLABEL;
1452       break;
1453
1454     case R_HPPA_NONE:
1455     case R_HPPA_ABS_CALL:
1456     case R_HPPA_PCREL_CALL:
1457     case R_HPPA_COMPLEX:
1458     case R_HPPA_COMPLEX_PCREL_CALL:
1459     case R_HPPA_COMPLEX_ABS_CALL:
1460       /* Right now we can default all these.  */
1461       break;
1462     }
1463   return final_types;
1464 }
1465
1466 /* Return the address of the correct entry in the PA SOM relocation
1467    howto table.  */
1468
1469 static const reloc_howto_type *
1470 som_bfd_reloc_type_lookup (arch, code)
1471      bfd_arch_info_type *arch;
1472      bfd_reloc_code_real_type code;
1473 {
1474   if ((int) code < (int) R_NO_RELOCATION + 255)
1475     {
1476       BFD_ASSERT ((int) som_hppa_howto_table[(int) code].type == (int) code);
1477       return &som_hppa_howto_table[(int) code];
1478     }
1479
1480   return (reloc_howto_type *) 0;
1481 }
1482
1483 /* Perform some initialization for an object.  Save results of this
1484    initialization in the BFD.  */
1485
1486 static bfd_target *
1487 som_object_setup (abfd, file_hdrp, aux_hdrp)
1488      bfd *abfd;
1489      struct header *file_hdrp;
1490      struct som_exec_auxhdr *aux_hdrp;
1491 {
1492   /* som_mkobject will set bfd_error if som_mkobject fails.  */
1493   if (som_mkobject (abfd) != true)
1494     return 0;
1495
1496   /* Set BFD flags based on what information is available in the SOM.  */
1497   abfd->flags = NO_FLAGS;
1498   if (! file_hdrp->entry_offset)
1499     abfd->flags |= HAS_RELOC;
1500   else
1501     abfd->flags |= EXEC_P;
1502   if (file_hdrp->symbol_total)
1503     abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
1504
1505   bfd_get_start_address (abfd) = aux_hdrp->exec_entry;
1506   bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 0);
1507   bfd_get_symcount (abfd) = file_hdrp->symbol_total;
1508
1509   /* Initialize the saved symbol table and string table to NULL.  
1510      Save important offsets and sizes from the SOM header into
1511      the BFD.  */
1512   obj_som_stringtab (abfd) = (char  *) NULL;
1513   obj_som_symtab (abfd) = (som_symbol_type *) NULL;
1514   obj_som_stringtab_size (abfd) = file_hdrp->symbol_strings_size;
1515   obj_som_sym_filepos (abfd) = file_hdrp->symbol_location;
1516   obj_som_str_filepos (abfd) = file_hdrp->symbol_strings_location;
1517   obj_som_reloc_filepos (abfd) = file_hdrp->fixup_request_location;
1518
1519   return abfd->xvec;
1520 }
1521
1522 /* Create a new BFD section for NAME.  If NAME already exists, then create a
1523    new unique name, with NAME as the prefix.  This exists because SOM .o files
1524    may have more than one $CODE$ subspace.  */
1525
1526 static asection *
1527 make_unique_section (abfd, name, num)
1528      bfd *abfd;
1529      CONST char *name;
1530      int num;
1531 {
1532   asection *sect;
1533   char *newname;
1534   char altname[100];
1535
1536   sect = bfd_make_section (abfd, name);
1537   while (!sect)
1538     {
1539       sprintf (altname, "%s-%d", name, num++);
1540       sect = bfd_make_section (abfd, altname);
1541     }
1542
1543   newname = bfd_alloc (abfd, strlen (sect->name) + 1);
1544   strcpy (newname, sect->name);
1545
1546   sect->name = newname;
1547   return sect;
1548 }
1549
1550 /* Convert all of the space and subspace info into BFD sections.  Each space
1551    contains a number of subspaces, which in turn describe the mapping between
1552    regions of the exec file, and the address space that the program runs in.
1553    BFD sections which correspond to spaces will overlap the sections for the
1554    associated subspaces.  */
1555
1556 static boolean
1557 setup_sections (abfd, file_hdr)
1558      bfd *abfd;
1559      struct header *file_hdr;
1560 {
1561   char *space_strings;
1562   int space_index;
1563   unsigned int total_subspaces = 0;
1564
1565   /* First, read in space names */
1566
1567   space_strings = alloca (file_hdr->space_strings_size);
1568   if (!space_strings)
1569     return false;
1570
1571   if (bfd_seek (abfd, file_hdr->space_strings_location, SEEK_SET) < 0)
1572     return false;
1573   if (bfd_read (space_strings, 1, file_hdr->space_strings_size, abfd)
1574       != file_hdr->space_strings_size)
1575     return false;
1576
1577   /* Loop over all of the space dictionaries, building up sections */
1578   for (space_index = 0; space_index < file_hdr->space_total; space_index++)
1579     {
1580       struct space_dictionary_record space;
1581       struct subspace_dictionary_record subspace, save_subspace;
1582       int subspace_index;
1583       asection *space_asect;
1584
1585       /* Read the space dictionary element */
1586       if (bfd_seek (abfd, file_hdr->space_location
1587                     + space_index * sizeof space, SEEK_SET) < 0)
1588         return false;
1589       if (bfd_read (&space, 1, sizeof space, abfd) != sizeof space)
1590         return false;
1591
1592       /* Setup the space name string */
1593       space.name.n_name = space.name.n_strx + space_strings;
1594
1595       /* Make a section out of it */
1596       space_asect = make_unique_section (abfd, space.name.n_name, space_index);
1597       if (!space_asect)
1598         return false;
1599
1600       /* Now, read in the first subspace for this space */
1601       if (bfd_seek (abfd, file_hdr->subspace_location
1602                     + space.subspace_index * sizeof subspace,
1603                     SEEK_SET) < 0)
1604         return false;
1605       if (bfd_read (&subspace, 1, sizeof subspace, abfd) != sizeof subspace)
1606         return false;
1607       /* Seek back to the start of the subspaces for loop below */
1608       if (bfd_seek (abfd, file_hdr->subspace_location
1609                     + space.subspace_index * sizeof subspace,
1610                     SEEK_SET) < 0)
1611         return false;
1612
1613       /* Setup the start address and file loc from the first subspace record */
1614       space_asect->vma = subspace.subspace_start;
1615       space_asect->filepos = subspace.file_loc_init_value;
1616       space_asect->alignment_power = log2 (subspace.alignment);
1617
1618       /* Initialize save_subspace so we can reliably determine if this
1619          loop placed any useful values into it.  */
1620       bzero (&save_subspace, sizeof (struct subspace_dictionary_record));
1621
1622       /* Loop over the rest of the subspaces, building up more sections */
1623       for (subspace_index = 0; subspace_index < space.subspace_quantity;
1624            subspace_index++)
1625         {
1626           asection *subspace_asect;
1627
1628           /* Read in the next subspace */
1629           if (bfd_read (&subspace, 1, sizeof subspace, abfd)
1630               != sizeof subspace)
1631             return false;
1632
1633           /* Setup the subspace name string */
1634           subspace.name.n_name = subspace.name.n_strx + space_strings;
1635
1636           /* Make a section out of this subspace */
1637           subspace_asect = make_unique_section (abfd, subspace.name.n_name,
1638                                      space.subspace_index + subspace_index);
1639
1640           if (!subspace_asect)
1641             return false;
1642
1643           /* Keep an easy mapping between subspaces and sections.  */
1644           som_section_data (subspace_asect)->subspace_index 
1645             = total_subspaces++;
1646
1647           /* Set SEC_READONLY and SEC_CODE/SEC_DATA as specified
1648              by the access_control_bits in the subspace header.  */
1649           switch (subspace.access_control_bits >> 4)
1650             {
1651             /* Readonly data.  */  
1652             case 0x0:
1653               subspace_asect->flags |= SEC_DATA | SEC_READONLY;
1654               break;
1655
1656             /* Normal data.  */  
1657             case 0x1:
1658               subspace_asect->flags |= SEC_DATA;
1659               break;
1660
1661             /* Readonly code and the gateways.
1662                Gateways have other attributes which do not map
1663                into anything BFD knows about.  */
1664             case 0x2:
1665             case 0x4:
1666             case 0x5:
1667             case 0x6:
1668             case 0x7:
1669               subspace_asect->flags |= SEC_CODE | SEC_READONLY;
1670               break;
1671
1672             /* dynamic (writable) code.  */
1673             case 0x3:
1674               subspace_asect->flags |= SEC_CODE;
1675               break;
1676             }
1677           
1678           if (subspace.dup_common || subspace.is_common) 
1679             subspace_asect->flags |= SEC_IS_COMMON;
1680           else if (subspace.subspace_length > 0)
1681             subspace_asect->flags |= SEC_HAS_CONTENTS;
1682           if (subspace.is_loadable)
1683             subspace_asect->flags |= SEC_ALLOC | SEC_LOAD;
1684           if (subspace.code_only)
1685             subspace_asect->flags |= SEC_CODE;
1686
1687           /* Both file_loc_init_value and initialization_length will
1688              be zero for a BSS like subspace.  */
1689           if (subspace.file_loc_init_value == 0
1690               && subspace.initialization_length == 0)
1691             subspace_asect->flags &= ~(SEC_DATA | SEC_LOAD);
1692
1693           /* This subspace has relocations.
1694              The fixup_request_quantity is a byte count for the number of
1695              entries in the relocation stream; it is not the actual number
1696              of relocations in the subspace.  */
1697           if (subspace.fixup_request_quantity != 0)
1698             {
1699               subspace_asect->flags |= SEC_RELOC;
1700               subspace_asect->rel_filepos = subspace.fixup_request_index;
1701               som_section_data (subspace_asect)->reloc_size
1702                 = subspace.fixup_request_quantity;
1703               /* We can not determine this yet.  When we read in the 
1704                  relocation table the correct value will be filled in.  */
1705               subspace_asect->reloc_count = -1;
1706             }
1707
1708           /* Update save_subspace if appropriate.  */
1709           if (subspace.file_loc_init_value > save_subspace.file_loc_init_value)
1710             save_subspace = subspace;
1711
1712           subspace_asect->vma = subspace.subspace_start;
1713           subspace_asect->_cooked_size = subspace.subspace_length;
1714           subspace_asect->_raw_size = subspace.subspace_length;
1715           subspace_asect->alignment_power = log2 (subspace.alignment);
1716           subspace_asect->filepos = subspace.file_loc_init_value;
1717         }
1718
1719       /* Yow! there is no subspace within the space which actually 
1720          has initialized information in it; this should never happen
1721          as far as I know.  */
1722       if (!save_subspace.file_loc_init_value)
1723         abort ();
1724
1725       /* Setup the sizes for the space section based upon the info in the
1726          last subspace of the space.  */
1727       space_asect->_cooked_size = save_subspace.subspace_start
1728         - space_asect->vma + save_subspace.subspace_length;
1729       space_asect->_raw_size = save_subspace.file_loc_init_value
1730         - space_asect->filepos + save_subspace.initialization_length;
1731     }
1732   return true;
1733 }
1734
1735 /* Read in a SOM object and make it into a BFD.  */
1736
1737 static bfd_target *
1738 som_object_p (abfd)
1739      bfd *abfd;
1740 {
1741   struct header file_hdr;
1742   struct som_exec_auxhdr aux_hdr;
1743
1744   if (bfd_read ((PTR) & file_hdr, 1, FILE_HDR_SIZE, abfd) != FILE_HDR_SIZE)
1745     {
1746       bfd_error = system_call_error;
1747       return 0;
1748     }
1749
1750   if (!_PA_RISC_ID (file_hdr.system_id))
1751     {
1752       bfd_error = wrong_format;
1753       return 0;
1754     }
1755
1756   switch (file_hdr.a_magic)
1757     {
1758     case RELOC_MAGIC:
1759     case EXEC_MAGIC:
1760     case SHARE_MAGIC:
1761     case DEMAND_MAGIC:
1762 #ifdef DL_MAGIC
1763     case DL_MAGIC:
1764 #endif
1765 #ifdef SHL_MAGIC
1766     case SHL_MAGIC:
1767 #endif
1768 #ifdef EXECLIBMAGIC
1769     case EXECLIBMAGIC:
1770 #endif
1771 #ifdef SHARED_MAGIC_CNX
1772     case SHARED_MAGIC_CNX:
1773 #endif
1774       break;
1775     default:
1776       bfd_error = wrong_format;
1777       return 0;
1778     }
1779
1780   if (file_hdr.version_id != VERSION_ID
1781       && file_hdr.version_id != NEW_VERSION_ID)
1782     {
1783       bfd_error = wrong_format;
1784       return 0;
1785     }
1786
1787   /* If the aux_header_size field in the file header is zero, then this
1788      object is an incomplete executable (a .o file).  Do not try to read
1789      a non-existant auxiliary header.  */
1790   bzero (&aux_hdr, sizeof (struct som_exec_auxhdr));
1791   if (file_hdr.aux_header_size != 0)
1792     {
1793       if (bfd_read ((PTR) & aux_hdr, 1, AUX_HDR_SIZE, abfd) != AUX_HDR_SIZE)
1794         {
1795           bfd_error = wrong_format;
1796           return 0;
1797         }
1798     }
1799
1800   if (!setup_sections (abfd, &file_hdr))
1801     {
1802       /* setup_sections does not bubble up a bfd error code.  */
1803       bfd_error = bad_value;
1804       return 0;
1805     }
1806
1807   /* This appears to be a valid SOM object.  Do some initialization.  */
1808   return som_object_setup (abfd, &file_hdr, &aux_hdr);
1809 }
1810
1811 /* Create a SOM object.  */
1812
1813 static boolean
1814 som_mkobject (abfd)
1815      bfd *abfd;
1816 {
1817   /* Allocate memory to hold backend information.  */
1818   abfd->tdata.som_data = (struct som_data_struct *)
1819     bfd_zalloc (abfd, sizeof (struct som_data_struct));
1820   if (abfd->tdata.som_data == NULL)
1821     {
1822       bfd_error = no_memory;
1823       return false;
1824     }
1825   obj_som_file_hdr (abfd)
1826     = (struct header *) bfd_zalloc (abfd, sizeof (struct header));
1827   if (obj_som_file_hdr (abfd) == NULL)
1828
1829     {
1830       bfd_error = no_memory;
1831       return false;
1832     }
1833   return true;
1834 }
1835
1836 /* Initialize some information in the file header.  This routine makes
1837    not attempt at doing the right thing for a full executable; it
1838    is only meant to handle relocatable objects.  */
1839
1840 static boolean
1841 som_prep_headers (abfd)
1842      bfd *abfd;
1843 {
1844   struct header *file_hdr = obj_som_file_hdr (abfd);
1845   asection *section;
1846
1847   /* FIXME.  This should really be conditional based on whether or not
1848      PA1.1 instructions/registers have been used.  */
1849   file_hdr->system_id = HP9000S800_ID;
1850
1851   /* FIXME.  Only correct for building relocatable objects.  */
1852   if (abfd->flags & EXEC_P)
1853     abort ();
1854   else
1855     file_hdr->a_magic = RELOC_MAGIC;
1856
1857   /* Only new format SOM is supported.  */
1858   file_hdr->version_id = NEW_VERSION_ID;
1859
1860   /* These fields are optional, and embedding timestamps is not always
1861      a wise thing to do, it makes comparing objects during a multi-stage
1862      bootstrap difficult.  */
1863   file_hdr->file_time.secs = 0;
1864   file_hdr->file_time.nanosecs = 0; 
1865
1866   if (abfd->flags & EXEC_P)
1867     abort ();
1868   else
1869     {
1870       file_hdr->entry_space = 0;
1871       file_hdr->entry_subspace = 0;
1872       file_hdr->entry_offset = 0;
1873     }
1874   
1875   /* FIXME.  I do not know if we ever need to put anything other
1876      than zero in this field.  */
1877   file_hdr->presumed_dp = 0;
1878
1879   /* Now iterate over the sections translating information from
1880      BFD sections to SOM spaces/subspaces.  */
1881
1882   for (section = abfd->sections; section != NULL; section = section->next)
1883     {
1884       /* Ignore anything which has not been marked as a space or
1885          subspace.  */
1886       if (som_section_data (section)->is_space == 0
1887
1888           && som_section_data (section)->is_subspace == 0)
1889         continue;
1890
1891       if (som_section_data (section)->is_space)
1892         {
1893           /* Set space attributes.  Note most attributes of SOM spaces
1894              are set based on the subspaces it contains.  */
1895           som_section_data (section)->space_dict.loader_fix_index = -1;
1896           som_section_data (section)->space_dict.init_pointer_index = -1;
1897         }
1898       else
1899         {
1900           /* Set subspace attributes.  Basic stuff is done here, additional
1901              attributes are filled in later as more information becomes
1902              available.  */
1903           if (section->flags & SEC_IS_COMMON)
1904             {
1905               som_section_data (section)->subspace_dict.dup_common = 1;
1906               som_section_data (section)->subspace_dict.is_common = 1;
1907             }
1908
1909           if (section->flags & SEC_ALLOC)
1910             som_section_data (section)->subspace_dict.is_loadable = 1;
1911
1912           if (section->flags & SEC_CODE)
1913             som_section_data (section)->subspace_dict.code_only = 1;
1914
1915           som_section_data (section)->subspace_dict.subspace_start = 
1916             section->vma;
1917           som_section_data (section)->subspace_dict.subspace_length =
1918             bfd_section_size (abfd, section);
1919           som_section_data (section)->subspace_dict.initialization_length =
1920             bfd_section_size (abfd, section);
1921           som_section_data (section)->subspace_dict.alignment = 
1922             1 << section->alignment_power;
1923         }
1924     }
1925   return true;
1926 }
1927
1928 /* Count and return the number of spaces attached to the given BFD.  */
1929
1930 static unsigned long
1931 som_count_spaces (abfd)
1932      bfd *abfd;
1933 {
1934   int count = 0;
1935   asection *section;
1936
1937   for (section = abfd->sections; section != NULL; section = section->next)
1938     count += som_section_data (section)->is_space;
1939
1940   return count;
1941 }
1942
1943 /* Count the number of subspaces attached to the given BFD.  */
1944
1945 static unsigned long
1946 som_count_subspaces (abfd)
1947      bfd *abfd;
1948 {
1949   int count = 0;
1950   asection *section;
1951
1952   for (section = abfd->sections; section != NULL; section = section->next)
1953     count += som_section_data (section)->is_subspace;
1954
1955   return count;
1956 }
1957
1958 /* Return -1, 0, 1 indicating the relative ordering of sym1 and sym2.
1959
1960    We desire symbols to be ordered starting with the symbol with the
1961    highest relocation count down to the symbol with the lowest relocation
1962    count.  Doing so compacts the relocation stream.  */
1963
1964 static int
1965 compare_syms (sym1, sym2)
1966      asymbol **sym1;
1967      asymbol **sym2;
1968
1969 {
1970   unsigned int count1, count2;
1971   
1972   /* Get relocation count for each symbol.  Note that the count
1973      is stored in the udata pointer for section symbols!  */
1974   if ((*sym1)->flags & BSF_SECTION_SYM)
1975     count1 = (int)(*sym1)->udata;
1976   else
1977     count1 = (*som_symbol_data ((*sym1)))->reloc_count;
1978
1979   if ((*sym2)->flags & BSF_SECTION_SYM)
1980     count2 = (int)(*sym2)->udata;
1981   else
1982     count2 = (*som_symbol_data ((*sym2)))->reloc_count;
1983
1984   /* Return the appropriate value.  */
1985   if (count1 < count2)
1986     return 1;
1987   else if (count1 > count2)
1988     return -1;
1989   return 0;
1990 }
1991
1992 /* Perform various work in preparation for emitting the fixup stream.  */
1993
1994 static void
1995 som_prep_for_fixups (abfd, syms, num_syms)
1996      bfd *abfd;
1997      asymbol **syms;
1998      unsigned long num_syms;
1999 {
2000   int i;
2001   asection *section;
2002
2003   /* Most SOM relocations involving a symbol have a length which is
2004      dependent on the index of the symbol.  So symbols which are
2005      used often in relocations should have a small index.  */
2006
2007   /* First initialize the counters for each symbol.  */
2008   for (i = 0; i < num_syms; i++)
2009     {
2010       /* Handle a section symbol; these have no pointers back to the 
2011          SOM symbol info.  So we just use the pointer field (udata)
2012          to hold the relocation count.
2013
2014          FIXME.  While we're here set the name of any section symbol
2015          to something which will not screw GDB.  How do other formats
2016          deal with this?!?  */
2017       if (som_symbol_data (syms[i]) == NULL)
2018         {
2019           syms[i]->flags |= BSF_SECTION_SYM;
2020           syms[i]->name = "L$0\002";
2021           syms[i]->udata = (PTR) 0;
2022         }
2023       else
2024         (*som_symbol_data (syms[i]))->reloc_count = 0;
2025     }
2026
2027   /* Now that the counters are initialized, make a weighted count
2028      of how often a given symbol is used in a relocation.  */
2029   for (section = abfd->sections; section != NULL; section = section->next)
2030     {
2031       int i;
2032
2033       /* Does this section have any relocations?  */
2034       if (section->reloc_count <= 0)
2035         continue;
2036
2037       /* Walk through each relocation for this section.  */
2038       for (i = 1; i < section->reloc_count; i++)
2039         {
2040           arelent *reloc = section->orelocation[i];
2041           int scale;
2042
2043           /* If no symbol, then there is no counter to increase.  */
2044           if (reloc->sym_ptr_ptr == NULL)
2045             continue;
2046
2047           /* Scaling to encourage symbols involved in R_DP_RELATIVE 
2048              and R_CODE_ONE_SYMBOL relocations to come first.  These
2049              two relocations have single byte versions if the symbol
2050              index is very small.  */
2051           if (reloc->howto->type == R_DP_RELATIVE
2052               || reloc->howto->type == R_CODE_ONE_SYMBOL)
2053             scale = 2;
2054           else
2055             scale = 1;
2056
2057           /* Handle section symbols by ramming the count in the udata
2058              field.  It will not be used and the count is very important
2059              for these symbols.  */
2060           if ((*reloc->sym_ptr_ptr)->flags & BSF_SECTION_SYM)
2061             {
2062               (*reloc->sym_ptr_ptr)->udata =
2063                 (PTR) ((int) (*reloc->sym_ptr_ptr)->udata + scale);
2064               continue;
2065             }
2066
2067           /* A normal symbol.  Increment the count.  */
2068           (*som_symbol_data ((*reloc->sym_ptr_ptr)))->reloc_count += scale;
2069         }
2070     }
2071
2072   /* Now sort the symbols.  */
2073   qsort (syms, num_syms, sizeof (asymbol *), compare_syms);
2074
2075   /* Compute the symbol indexes, they will be needed by the relocation
2076      code.  */
2077   for (i = 0; i < num_syms; i++)
2078     {
2079       /* A section symbol.  Again, there is no pointer to backend symbol
2080          information, so we reuse (abuse) the udata field again.  */
2081       if (syms[i]->flags & BSF_SECTION_SYM)
2082         syms[i]->udata = (PTR) i;
2083       else
2084         (*som_symbol_data (syms[i]))->index = i;
2085     }
2086 }
2087
2088 static boolean
2089 som_write_fixups (abfd, current_offset, total_reloc_sizep)
2090      bfd *abfd;
2091      unsigned long current_offset;
2092      unsigned int *total_reloc_sizep;
2093 {
2094   unsigned int i, j;
2095   unsigned char *tmp_space, *p;
2096   unsigned int total_reloc_size = 0;
2097   unsigned int subspace_reloc_size = 0;
2098   unsigned int num_spaces = obj_som_file_hdr (abfd)->space_total;
2099   asection *section = abfd->sections;
2100
2101   /* Get a chunk of memory that we can use as buffer space, then throw
2102      away.  */
2103   tmp_space = alloca (SOM_TMP_BUFSIZE);
2104   bzero (tmp_space, SOM_TMP_BUFSIZE);
2105   p = tmp_space;
2106
2107   /* All the fixups for a particular subspace are emitted in a single
2108      stream.  All the subspaces for a particular space are emitted
2109      as a single stream.
2110
2111      So, to get all the locations correct one must iterate through all the
2112      spaces, for each space iterate through its subspaces and output a
2113      fixups stream.  */
2114   for (i = 0; i < num_spaces; i++)
2115     {
2116       asection *subsection;
2117
2118       /* Find a space.  */
2119       while (som_section_data (section)->is_space == 0)
2120         section = section->next;
2121
2122       /* Now iterate through each of its subspaces.  */
2123       for (subsection = abfd->sections;
2124            subsection != NULL;
2125            subsection = subsection->next)
2126         {
2127           int reloc_offset, current_rounding_mode;
2128
2129           /* Find a subspace of this space.  */
2130           if (som_section_data (subsection)->is_subspace == 0
2131               || som_section_data (subsection)->containing_space != section)
2132             continue;
2133
2134           /* If this subspace had no relocations, then we're finished 
2135              with it.  */
2136           if (subsection->reloc_count <= 0)
2137             {
2138               som_section_data (subsection)->subspace_dict.fixup_request_index
2139                 = -1;
2140               continue;
2141             }
2142
2143           /* This subspace has some relocations.  Put the relocation stream
2144              index into the subspace record.  */
2145           som_section_data (subsection)->subspace_dict.fixup_request_index
2146             = total_reloc_size;
2147
2148           /* To make life easier start over with a clean slate for 
2149              each subspace.  Seek to the start of the relocation stream
2150              for this subspace in preparation for writing out its fixup
2151              stream.  */
2152           if (bfd_seek (abfd, current_offset + total_reloc_size, SEEK_SET) != 0)
2153             {
2154               bfd_error = system_call_error;
2155               return false;
2156             }
2157
2158           /* Buffer space has already been allocated.  Just perform some
2159              initialization here.  */
2160           p = tmp_space;
2161           subspace_reloc_size = 0;
2162           reloc_offset = 0;
2163           som_initialize_reloc_queue (reloc_queue);
2164           current_rounding_mode = R_N_MODE;
2165
2166           /* Translate each BFD relocation into one or more SOM 
2167              relocations.  */
2168           for (j = 0; j < subsection->reloc_count; j++)
2169             {
2170               arelent *bfd_reloc = subsection->orelocation[j];
2171               unsigned int skip;
2172               int sym_num;
2173
2174               /* Get the symbol number.  Remember it's stored in a 
2175                  special place for section symbols.  */
2176               if ((*bfd_reloc->sym_ptr_ptr)->flags & BSF_SECTION_SYM)
2177                 sym_num = (int) (*bfd_reloc->sym_ptr_ptr)->udata;
2178               else
2179                 sym_num = (*som_symbol_data ((*bfd_reloc->sym_ptr_ptr)))->index;
2180               
2181               /* If there is not enough room for the next couple relocations,
2182                  then dump the current buffer contents now.  Also reinitialize
2183                  the relocation queue. 
2184
2185                  FIXME.  We assume here that no BFD relocation will expand
2186                  to more than 100 bytes of SOM relocations.  This should (?!?)
2187                  be quite safe.  */
2188               if (p - tmp_space + 100 > SOM_TMP_BUFSIZE)
2189                 {
2190                   if (bfd_write ((PTR) tmp_space, p - tmp_space, 1, abfd)
2191                       != p - tmp_space)
2192                     {
2193                       bfd_error = system_call_error;
2194                       return false;
2195                     }
2196                   p = tmp_space;
2197                   som_initialize_reloc_queue (reloc_queue);
2198                 }
2199
2200               /* Emit R_NO_RELOCATION fixups to map any bytes which were
2201                  skipped.  */
2202               skip = bfd_reloc->address - reloc_offset;
2203               p = som_reloc_skip (abfd, skip, p,
2204                                   &subspace_reloc_size, reloc_queue);
2205
2206               /* Update reloc_offset for the next iteration.
2207
2208                  Many relocations do not consume input bytes.  They
2209                  are markers, or set state necessary to perform some
2210                  later relocation.  */
2211               switch (bfd_reloc->howto->type)
2212                 {
2213                 /* This only needs to handle relocations that may be
2214                    made by hppa_som_gen_reloc.  */
2215                 case R_ENTRY:
2216                 case R_EXIT:
2217                 case R_N_MODE:
2218                 case R_S_MODE:
2219                 case R_D_MODE:
2220                 case R_R_MODE:
2221                 case R_FSEL:
2222                 case R_LSEL:
2223                 case R_RSEL:
2224                   reloc_offset = bfd_reloc->address;
2225                   break;
2226
2227                 default:
2228                   reloc_offset = bfd_reloc->address + 4;
2229                   break;
2230                 }
2231
2232               /* Now the actual relocation we care about.  */
2233               switch (bfd_reloc->howto->type)
2234                 {
2235                 case R_PCREL_CALL:
2236                 case R_ABS_CALL:
2237                   p = som_reloc_call (abfd, p, &subspace_reloc_size,
2238                                       bfd_reloc, sym_num, reloc_queue);
2239                   break;
2240
2241                 case R_CODE_ONE_SYMBOL:
2242                 case R_DP_RELATIVE:
2243                   /* Account for any addend.  */
2244                   if (bfd_reloc->addend)
2245                     p = som_reloc_addend (abfd, bfd_reloc->addend, p, 
2246                                           &subspace_reloc_size, reloc_queue);
2247
2248                   if (sym_num < 0x20)
2249                     {
2250                       bfd_put_8 (abfd, bfd_reloc->howto->type + sym_num, p);
2251                       subspace_reloc_size += 1;
2252                       p += 1;
2253                     }
2254                   else if (sym_num < 0x100)
2255                     {
2256                       bfd_put_8 (abfd, bfd_reloc->howto->type + 32, p);
2257                       bfd_put_8 (abfd, sym_num, p + 1);
2258                       p = try_prev_fixup (abfd, &subspace_reloc_size, p,
2259                                           2, reloc_queue);
2260                     }
2261                   else if (sym_num < 0x10000000)
2262                     {
2263                       bfd_put_8 (abfd, bfd_reloc->howto->type + 33, p);
2264                       bfd_put_8 (abfd, sym_num >> 16, p + 1);
2265                       bfd_put_16 (abfd, sym_num, p + 2); 
2266                       p = try_prev_fixup (abfd, &subspace_reloc_size,
2267                                           p, 4, reloc_queue);
2268                     }
2269                   else
2270                     abort ();
2271                   break;
2272
2273                 case R_DATA_ONE_SYMBOL:
2274                 case R_DATA_PLABEL:
2275                 case R_CODE_PLABEL:
2276                 case R_DLT_REL:
2277                   /* Account for any addend.  */
2278                   if (bfd_reloc->addend)
2279                     p = som_reloc_addend (abfd, bfd_reloc->addend, p, 
2280                                           &subspace_reloc_size, reloc_queue);
2281
2282                   if (sym_num < 0x100)
2283                     {
2284                       bfd_put_8 (abfd, bfd_reloc->howto->type, p);
2285                       bfd_put_8 (abfd, sym_num, p + 1);
2286                       p = try_prev_fixup (abfd, &subspace_reloc_size, p,
2287                                           2, reloc_queue);
2288                     }
2289                   else if (sym_num < 0x10000000)
2290                     {
2291                       bfd_put_8 (abfd, bfd_reloc->howto->type + 1, p);
2292                       bfd_put_8 (abfd, sym_num >> 16, p + 1);
2293                       bfd_put_16 (abfd, sym_num, p + 2); 
2294                       p = try_prev_fixup (abfd, &subspace_reloc_size,
2295                                           p, 4, reloc_queue);
2296                     }
2297                   else
2298                     abort ();
2299                   break;
2300
2301                 case R_ENTRY:
2302                   {
2303                     int *descp
2304                        = (int *) (*som_symbol_data ((*bfd_reloc->sym_ptr_ptr)))->unwind;
2305                     bfd_put_8 (abfd, R_ENTRY, p);
2306                     bfd_put_32 (abfd, descp[0], p + 1);
2307                     bfd_put_32 (abfd, descp[1], p + 5);
2308                     p = try_prev_fixup (abfd, &subspace_reloc_size,
2309                                         p, 9, reloc_queue);
2310                     break;
2311                   }
2312                   
2313                 case R_EXIT:
2314                   bfd_put_8 (abfd, R_EXIT, p);
2315                   subspace_reloc_size += 1;
2316                   p += 1;
2317                   break;
2318
2319                 case R_N_MODE:
2320                 case R_S_MODE:
2321                 case R_D_MODE:
2322                 case R_R_MODE:
2323                   /* If this relocation requests the current rounding
2324                      mode, then it is redundant.  */
2325                   if (bfd_reloc->howto->type != current_rounding_mode)
2326                     {
2327                       bfd_put_8 (abfd, bfd_reloc->howto->type, p);
2328                       subspace_reloc_size += 1;
2329                       p += 1;
2330                       current_rounding_mode = bfd_reloc->howto->type;
2331                     }
2332                   break;
2333
2334                 case R_FSEL:
2335                 case R_LSEL:
2336                 case R_RSEL:
2337                   bfd_put_8 (abfd, bfd_reloc->howto->type, p);
2338                   subspace_reloc_size += 1;
2339                   p += 1;
2340                   break;
2341
2342                 /* Put a "R_RESERVED" relocation in the stream if
2343                    we hit something we do not understand.  The linker
2344                    will complain loudly if this ever happens.  */
2345                 default:
2346                   bfd_put_8 (abfd, 0xff, p);
2347                   subspace_reloc_size += 1;
2348                   p += 1;
2349                   break;
2350                 }
2351             }
2352
2353           /* Last BFD relocation for a subspace has been processed.
2354              Map the rest of the subspace with R_NO_RELOCATION fixups.  */
2355           p = som_reloc_skip (abfd, bfd_section_size (abfd, subsection) 
2356                                       - reloc_offset,
2357                               p, &subspace_reloc_size, reloc_queue);
2358
2359           /* Scribble out the relocations.  */
2360           if (bfd_write ((PTR) tmp_space, p - tmp_space, 1, abfd)
2361               != p - tmp_space)
2362             {
2363               bfd_error = system_call_error;
2364               return false;
2365             }
2366           p = tmp_space;
2367
2368           total_reloc_size += subspace_reloc_size;
2369           som_section_data (subsection)->subspace_dict.fixup_request_quantity
2370             = subspace_reloc_size;
2371         }
2372       section = section->next;
2373     }
2374   *total_reloc_sizep = total_reloc_size;
2375   return true;
2376 }
2377
2378 /* Write out the space/subspace string table.  */
2379
2380 static boolean
2381 som_write_space_strings (abfd, current_offset, string_sizep)
2382      bfd *abfd;
2383      unsigned long current_offset;
2384      unsigned int *string_sizep;
2385 {
2386   unsigned char *tmp_space, *p;
2387   unsigned int strings_size = 0;
2388   asection *section;
2389
2390   /* Get a chunk of memory that we can use as buffer space, then throw
2391      away.  */
2392   tmp_space = alloca (SOM_TMP_BUFSIZE);
2393   bzero (tmp_space, SOM_TMP_BUFSIZE);
2394   p = tmp_space;
2395
2396   /* Seek to the start of the space strings in preparation for writing
2397      them out.  */
2398   if (bfd_seek (abfd, current_offset, SEEK_SET) != 0)
2399     {
2400       bfd_error = system_call_error;
2401       return false;
2402     }
2403
2404   /* Walk through all the spaces and subspaces (order is not important)
2405      building up and writing string table entries for their names.  */
2406   for (section = abfd->sections; section != NULL; section = section->next)
2407     {
2408       int length;
2409
2410       /* Only work with space/subspaces; avoid any other sections
2411          which might have been made (.text for example).  */
2412       if (som_section_data (section)->is_space == 0
2413           && som_section_data (section)->is_subspace == 0)
2414         continue;
2415
2416       /* Get the length of the space/subspace name.  */
2417       length = strlen (section->name);
2418
2419       /* If there is not enough room for the next entry, then dump the
2420          current buffer contents now.  Each entry will take 4 bytes to
2421          hold the string length + the string itself + null terminator.  */
2422       if (p - tmp_space + 5 + length > SOM_TMP_BUFSIZE)
2423         {
2424           if (bfd_write ((PTR) tmp_space, p - tmp_space, 1, abfd)
2425               != p - tmp_space) 
2426             {
2427               bfd_error = system_call_error;
2428               return false;
2429             }
2430           /* Reset to beginning of the buffer space.  */
2431           p = tmp_space;
2432         }
2433
2434       /* First element in a string table entry is the length of the
2435          string.  Alignment issues are already handled.  */
2436       bfd_put_32 (abfd, length, p);
2437       p += 4;
2438       strings_size += 4;
2439
2440       /* Record the index in the space/subspace records.  */
2441       if (som_section_data (section)->is_space)
2442         som_section_data (section)->space_dict.name.n_strx = strings_size;
2443       else
2444         som_section_data (section)->subspace_dict.name.n_strx = strings_size;
2445
2446       /* Next comes the string itself + a null terminator.  */
2447       strcpy (p, section->name);
2448       p += length + 1;
2449       strings_size += length + 1;
2450
2451       /* Always align up to the next word boundary.  */
2452       while (strings_size % 4)
2453         {
2454           bfd_put_8 (abfd, 0, p);
2455           p++;
2456           strings_size++;
2457         }
2458     }
2459
2460   /* Done with the space/subspace strings.  Write out any information
2461      contained in a partial block.  */
2462   if (bfd_write ((PTR) tmp_space, p - tmp_space, 1, abfd) != p - tmp_space)
2463     {
2464       bfd_error = system_call_error;
2465       return false;
2466     }
2467   *string_sizep = strings_size;
2468   return true;
2469 }
2470
2471 /* Write out the symbol string table.  */
2472
2473 static boolean
2474 som_write_symbol_strings (abfd, current_offset, syms, num_syms, string_sizep)
2475      bfd *abfd;
2476      unsigned long current_offset;
2477      asymbol **syms;
2478      unsigned int num_syms;
2479      unsigned int *string_sizep;
2480 {
2481   unsigned int i;
2482   unsigned char *tmp_space, *p;
2483   unsigned int strings_size = 0;
2484
2485   /* Get a chunk of memory that we can use as buffer space, then throw
2486      away.  */
2487   tmp_space = alloca (SOM_TMP_BUFSIZE);
2488   bzero (tmp_space, SOM_TMP_BUFSIZE);
2489   p = tmp_space;
2490
2491   /* Seek to the start of the space strings in preparation for writing
2492      them out.  */
2493   if (bfd_seek (abfd, current_offset, SEEK_SET) != 0)
2494     {
2495       bfd_error = system_call_error;
2496       return false;
2497     }
2498
2499   for (i = 0; i < num_syms; i++)
2500     {
2501       int length = strlen (syms[i]->name);
2502
2503       /* If there is not enough room for the next entry, then dump the
2504          current buffer contents now.  */
2505      if (p - tmp_space + 5 + length > SOM_TMP_BUFSIZE)
2506         {
2507           if (bfd_write ((PTR) tmp_space, p - tmp_space, 1, abfd)
2508               != p - tmp_space)
2509             {
2510               bfd_error = system_call_error;
2511               return false;
2512             }
2513           /* Reset to beginning of the buffer space.  */
2514           p = tmp_space;
2515         }
2516
2517       /* First element in a string table entry is the length of the
2518          string.  This must always be 4 byte aligned.  This is also
2519          an appropriate time to fill in the string index field in the
2520          symbol table entry.  */
2521       bfd_put_32 (abfd, length, p);
2522       strings_size += 4;
2523       p += 4;
2524
2525       /* Next comes the string itself + a null terminator.  */
2526       strcpy (p, syms[i]->name);
2527
2528       /* ACK.  FIXME.  */
2529       syms[i]->name = (char *)strings_size;
2530       p += length + 1;
2531       strings_size += length + 1;
2532
2533       /* Always align up to the next word boundary.  */
2534       while (strings_size % 4)
2535         {
2536           bfd_put_8 (abfd, 0, p);
2537           strings_size++;
2538           p++;
2539         }
2540     }
2541
2542   /* Scribble out any partial block.  */
2543   if (bfd_write ((PTR) tmp_space, p - tmp_space, 1, abfd) != p - tmp_space)
2544     {
2545       bfd_error = system_call_error;
2546       return false;
2547     }
2548
2549   *string_sizep = strings_size;
2550   return true;
2551 }
2552
2553 /* Compute variable information to be placed in the SOM headers, 
2554    space/subspace dictionaries, relocation streams, etc.  Begin
2555    writing parts of the object file.  */
2556
2557 static boolean 
2558 som_begin_writing (abfd)
2559      bfd *abfd;
2560 {
2561   unsigned long current_offset = 0;
2562   int strings_size = 0;
2563   unsigned int total_reloc_size = 0;
2564   unsigned long num_spaces, num_subspaces, num_syms, i;
2565   asection *section;
2566   asymbol **syms = bfd_get_outsymbols (abfd);
2567   unsigned int total_subspaces = 0;
2568
2569   /* The file header will always be first in an object file, 
2570      everything else can be in random locations.  To keep things
2571      "simple" BFD will lay out the object file in the manner suggested
2572      by the PRO ABI for PA-RISC Systems.  */
2573
2574   /* Before any output can really begin offsets for all the major
2575      portions of the object file must be computed.  So, starting
2576      with the initial file header compute (and sometimes write)
2577      each portion of the object file.  */
2578
2579   /* Make room for the file header, it's contents are not complete
2580      yet, so it can not be written at this time.  */
2581   current_offset += sizeof (struct header);  
2582
2583   /* Any auxiliary headers will follow the file header.  Right now
2584      we support only the copyright and version headers.  */
2585   obj_som_file_hdr (abfd)->aux_header_location = current_offset;
2586   obj_som_file_hdr (abfd)->aux_header_size = 0;
2587   if (obj_som_version_hdr (abfd) != NULL)
2588     {
2589       unsigned int len;
2590
2591       bfd_seek (abfd, current_offset, SEEK_SET);
2592
2593       /* Write the aux_id structure and the string length.  */
2594       len = sizeof (struct aux_id) + sizeof (unsigned int);
2595       obj_som_file_hdr (abfd)->aux_header_size += len;
2596       current_offset += len;
2597       if (bfd_write ((PTR) obj_som_version_hdr (abfd), len, 1, abfd) != len)
2598         {
2599           bfd_error = system_call_error;
2600           return false;
2601         }
2602
2603       /* Write the version string.  */
2604       len = obj_som_version_hdr (abfd)->header_id.length - sizeof (int);
2605       obj_som_file_hdr (abfd)->aux_header_size += len;
2606       current_offset += len;
2607       if (bfd_write ((PTR) obj_som_version_hdr (abfd)->user_string,
2608                      len, 1, abfd) != len)
2609         {
2610           bfd_error = system_call_error;
2611           return false;
2612         }
2613     }
2614
2615   if (obj_som_copyright_hdr (abfd) != NULL)
2616     {
2617       unsigned int len;
2618
2619       bfd_seek (abfd, current_offset, SEEK_SET);
2620
2621       /* Write the aux_id structure and the string length.  */
2622       len = sizeof (struct aux_id) + sizeof (unsigned int);
2623       obj_som_file_hdr (abfd)->aux_header_size += len;
2624       current_offset += len;
2625       if (bfd_write ((PTR) obj_som_copyright_hdr (abfd), len, 1, abfd) != len)
2626         {
2627           bfd_error = system_call_error;
2628           return false;
2629         }
2630
2631       /* Write the copyright string.  */
2632       len = obj_som_copyright_hdr (abfd)->header_id.length - sizeof (int);
2633       obj_som_file_hdr (abfd)->aux_header_size += len;
2634       current_offset += len;
2635       if (bfd_write ((PTR) obj_som_copyright_hdr (abfd)->copyright,
2636                      len, 1, abfd) != len)
2637         {
2638           bfd_error = system_call_error;
2639           return false;
2640         }
2641     }
2642
2643   /* Next comes the initialization pointers; we have no initialization
2644      pointers, so current offset does not change.  */
2645   obj_som_file_hdr (abfd)->init_array_location = current_offset;
2646   obj_som_file_hdr (abfd)->init_array_total = 0;
2647
2648   /* Next are the space records.  These are fixed length records.
2649
2650      Count the number of spaces to determine how much room is needed
2651      in the object file for the space records.
2652
2653      The names of the spaces are stored in a separate string table,
2654      and the index for each space into the string table is computed
2655      below.  Therefore, it is not possible to write the space headers
2656      at this time.  */
2657   num_spaces = som_count_spaces (abfd);
2658   obj_som_file_hdr (abfd)->space_location = current_offset;
2659   obj_som_file_hdr (abfd)->space_total = num_spaces;
2660   current_offset += num_spaces * sizeof (struct space_dictionary_record);
2661
2662   /* Next are the subspace records.  These are fixed length records.
2663
2664      Count the number of subspaes to determine how much room is needed
2665      in the object file for the subspace records.
2666
2667      A variety if fields in the subspace record are still unknown at
2668      this time (index into string table, fixup stream location/size, etc).  */
2669   num_subspaces = som_count_subspaces (abfd);
2670   obj_som_file_hdr (abfd)->subspace_location = current_offset;
2671   obj_som_file_hdr (abfd)->subspace_total = num_subspaces;
2672   current_offset += num_subspaces * sizeof (struct subspace_dictionary_record);
2673
2674   /* Next is the string table for the space/subspace names.  We will
2675      build and write the string table on the fly.  At the same time
2676      we will fill in the space/subspace name index fields.  */
2677
2678   /* The string table needs to be aligned on a word boundary.  */
2679   if (current_offset % 4)
2680     current_offset += (4 - (current_offset % 4));
2681
2682   /* Mark the offset of the space/subspace string table in the 
2683      file header.  */
2684   obj_som_file_hdr (abfd)->space_strings_location = current_offset;
2685
2686   /* Scribble out the space strings.  */
2687   if (som_write_space_strings (abfd, current_offset, &strings_size) == false)
2688     return false;
2689
2690   /* Record total string table size in the header and update the
2691      current offset.  */
2692   obj_som_file_hdr (abfd)->space_strings_size = strings_size;
2693   current_offset += strings_size;
2694
2695   /* Next is the symbol table.  These are fixed length records.
2696
2697      Count the number of symbols to determine how much room is needed
2698      in the object file for the symbol table.
2699
2700      The names of the symbols are stored in a separate string table,
2701      and the index for each symbol name into the string table is computed
2702      below.  Therefore, it is not possible to write the symobl table
2703      at this time.  */
2704   num_syms = bfd_get_symcount (abfd);
2705   obj_som_file_hdr (abfd)->symbol_location = current_offset;
2706   obj_som_file_hdr (abfd)->symbol_total = num_syms;
2707   current_offset += num_syms * sizeof (struct symbol_dictionary_record);
2708
2709   /* Do prep work before handling fixups.  */
2710   som_prep_for_fixups (abfd, syms, num_syms);
2711
2712   /* Next comes the fixup stream which starts on a word boundary.  */
2713   if (current_offset % 4)
2714     current_offset += (4 - (current_offset % 4)); 
2715   obj_som_file_hdr (abfd)->fixup_request_location = current_offset;
2716
2717   /* Write the fixups and update fields in subspace headers which
2718      relate to the fixup stream.  */
2719   if (som_write_fixups (abfd, current_offset, &total_reloc_size) == false)
2720     return false;
2721
2722   /* Record the total size of the fixup stream in the file header.  */
2723   obj_som_file_hdr (abfd)->fixup_request_total = total_reloc_size;
2724   current_offset += total_reloc_size;
2725
2726   /* Next are the symbol strings.
2727      Align them to a word boundary.  */
2728   if (current_offset % 4)
2729     current_offset += (4 - (current_offset % 4));
2730   obj_som_file_hdr (abfd)->symbol_strings_location = current_offset;
2731
2732   /* Scribble out the symbol strings.  */
2733   if (som_write_symbol_strings (abfd, current_offset, syms, 
2734                                 num_syms, &strings_size)
2735       == false)
2736     return false;
2737
2738   /* Record total string table size in header and update the
2739      current offset.  */
2740   obj_som_file_hdr (abfd)->symbol_strings_size = strings_size;
2741   current_offset += strings_size;
2742
2743   /* Next is the compiler records.  We do not use these.  */
2744   obj_som_file_hdr (abfd)->compiler_location = current_offset;
2745   obj_som_file_hdr (abfd)->compiler_total = 0;
2746
2747   /* Now compute the file positions for the loadable subspaces.  */
2748
2749   section = abfd->sections;
2750   for (i = 0; i < num_spaces; i++)
2751     {
2752       asection *subsection;
2753
2754       /* Find a space.  */
2755       while (som_section_data (section)->is_space == 0)
2756         section = section->next;
2757
2758       /* Now look for all its subspaces.  */
2759       for (subsection = abfd->sections;
2760            subsection != NULL;
2761            subsection = subsection->next)
2762         {
2763           
2764           if (som_section_data (subsection)->is_subspace == 0
2765               || som_section_data (subsection)->containing_space != section
2766               || (subsection->flags & SEC_ALLOC) == 0)
2767             continue;
2768
2769           som_section_data (subsection)->subspace_index = total_subspaces++;
2770           /* This is real data to be loaded from the file.  */
2771           if (subsection->flags & SEC_LOAD)
2772             {
2773               som_section_data (subsection)->subspace_dict.file_loc_init_value
2774                 = current_offset;
2775               section->filepos = current_offset;
2776               current_offset += bfd_section_size (abfd, subsection); 
2777             }
2778           /* Looks like uninitialized data.  */
2779           else
2780             {
2781               som_section_data (subsection)->subspace_dict.file_loc_init_value
2782                 = 0;
2783               som_section_data (subsection)->subspace_dict.
2784                 initialization_length = 0;
2785             }
2786         }
2787       /* Goto the next section.  */
2788       section = section->next; 
2789     }
2790
2791   /* Finally compute the file positions for unloadable subspaces.  */
2792
2793   obj_som_file_hdr (abfd)->unloadable_sp_location = current_offset;
2794   section = abfd->sections;
2795   for (i = 0; i < num_spaces; i++)
2796     {
2797       asection *subsection;
2798
2799       /* Find a space.  */
2800       while (som_section_data (section)->is_space == 0)
2801         section = section->next;
2802
2803       /* Now look for all its subspaces.  */
2804       for (subsection = abfd->sections;
2805            subsection != NULL;
2806            subsection = subsection->next)
2807         {
2808           
2809           if (som_section_data (subsection)->is_subspace == 0
2810               || som_section_data (subsection)->containing_space != section
2811               || (subsection->flags & SEC_ALLOC) != 0)
2812             continue;
2813
2814           som_section_data (subsection)->subspace_index = total_subspaces++;
2815           /* This is real data to be loaded from the file.  */
2816           if ((subsection->flags & SEC_LOAD) == 0)
2817             {
2818               som_section_data (subsection)->subspace_dict.file_loc_init_value
2819                 = current_offset;
2820               section->filepos = current_offset;
2821               current_offset += bfd_section_size (abfd, subsection); 
2822             }
2823           /* Looks like uninitialized data.  */
2824           else
2825             {
2826               som_section_data (subsection)->subspace_dict.file_loc_init_value
2827                 = 0;
2828               som_section_data (subsection)->subspace_dict.
2829                 initialization_length = bfd_section_size (abfd, subsection);
2830             }
2831         }
2832       /* Goto the next section.  */
2833       section = section->next; 
2834     }
2835
2836   obj_som_file_hdr (abfd)->unloadable_sp_size
2837     = current_offset - obj_som_file_hdr (abfd)->unloadable_sp_location;
2838
2839   /* Loader fixups are not supported in any way shape or form.  */
2840   obj_som_file_hdr (abfd)->loader_fixup_location = 0;
2841   obj_som_file_hdr (abfd)->loader_fixup_total = 0;
2842
2843   /* Done.  Store the total size of the SOM.  */
2844   obj_som_file_hdr (abfd)->som_length = current_offset;
2845   return true;
2846 }
2847
2848 /* Finally, scribble out the various headers to the disk.  */
2849
2850 static boolean
2851 som_write_headers (abfd)
2852      bfd *abfd;
2853 {
2854   int num_spaces = som_count_spaces (abfd);
2855   int i;
2856   int subspace_index = 0;
2857   file_ptr location;
2858   asection *section;
2859
2860   /* Subspaces are written first so that we can set up information
2861      about them in their containing spaces as the subspace is written.  */
2862
2863   /* Seek to the start of the subspace dictionary records.  */
2864   location = obj_som_file_hdr (abfd)->subspace_location;
2865   bfd_seek (abfd, location, SEEK_SET);
2866   section = abfd->sections;
2867   /* Now for each loadable space write out records for its subspaces.  */
2868   for (i = 0; i < num_spaces; i++)
2869     {
2870       asection *subsection;
2871
2872       /* Find a space.  */
2873       while (som_section_data (section)->is_space == 0)
2874         section = section->next;
2875
2876       /* Now look for all its subspaces.  */
2877       for (subsection = abfd->sections;
2878            subsection != NULL;
2879            subsection = subsection->next)
2880         {
2881           
2882           /* Skip any section which does not correspond to a space
2883              or subspace.  Or does not have SEC_ALLOC set (and therefore
2884              has no real bits on the disk).  */
2885           if (som_section_data (subsection)->is_subspace == 0
2886               || som_section_data (subsection)->containing_space != section
2887               || (subsection->flags & SEC_ALLOC) == 0)
2888             continue;
2889
2890           /* If this is the first subspace for this space, then save
2891              the index of the subspace in its containing space.  Also
2892              set "is_loadable" in the containing space.  */
2893
2894           if (som_section_data (section)->space_dict.subspace_quantity == 0)
2895             {
2896               som_section_data (section)->space_dict.is_loadable = 1;
2897               som_section_data (section)->space_dict.subspace_index
2898                 = subspace_index;
2899             }
2900
2901           /* Increment the number of subspaces seen and the number of
2902              subspaces contained within the current space.  */
2903           subspace_index++;
2904           som_section_data (section)->space_dict.subspace_quantity++;
2905
2906           /* Mark the index of the current space within the subspace's
2907              dictionary record.  */
2908           som_section_data (subsection)->subspace_dict.space_index = i;
2909           
2910           /* Dump the current subspace header.  */
2911           if (bfd_write ((PTR) &som_section_data (subsection)->subspace_dict,
2912                          sizeof (struct subspace_dictionary_record), 1, abfd)
2913               != sizeof (struct subspace_dictionary_record))
2914             {
2915               bfd_error = system_call_error;
2916               return false;
2917             }
2918         }
2919       /* Goto the next section.  */
2920       section = section->next; 
2921     }
2922
2923   /* Now repeat the process for unloadable subspaces.  */
2924   section = abfd->sections;
2925   /* Now for each space write out records for its subspaces.  */
2926   for (i = 0; i < num_spaces; i++)
2927     {
2928       asection *subsection;
2929
2930       /* Find a space.  */
2931       while (som_section_data (section)->is_space == 0)
2932         section = section->next;
2933
2934       /* Now look for all its subspaces.  */
2935       for (subsection = abfd->sections;
2936            subsection != NULL;
2937            subsection = subsection->next)
2938         {
2939           
2940           /* Skip any section which does not correspond to a space or
2941              subspace, or which SEC_ALLOC set (and therefore handled
2942              in the loadable spaces/subspaces code above.  */
2943
2944           if (som_section_data (subsection)->is_subspace == 0
2945               || som_section_data (subsection)->containing_space != section
2946               || (subsection->flags & SEC_ALLOC) != 0)
2947             continue;
2948
2949           /* If this is the first subspace for this space, then save
2950              the index of the subspace in its containing space.  Clear
2951              "is_loadable".  */
2952
2953           if (som_section_data (section)->space_dict.subspace_quantity == 0)
2954             {
2955               som_section_data (section)->space_dict.is_loadable = 0;
2956               som_section_data (section)->space_dict.subspace_index
2957                 = subspace_index;
2958             }
2959
2960           /* Increment the number of subspaces seen and the number of
2961              subspaces contained within the current space.  */
2962           som_section_data (section)->space_dict.subspace_quantity++;
2963           subspace_index++; 
2964
2965           /* Mark the index of the current space within the subspace's
2966              dictionary record.  */
2967           som_section_data (subsection)->subspace_dict.space_index = i;
2968           
2969           /* Dump this subspace header.  */
2970           if (bfd_write ((PTR) &som_section_data (subsection)->subspace_dict,
2971                          sizeof (struct subspace_dictionary_record), 1, abfd)
2972               != sizeof (struct subspace_dictionary_record))
2973             {
2974               bfd_error = system_call_error;
2975               return false;
2976             }
2977         }
2978       /* Goto the next section.  */
2979       section = section->next; 
2980     }
2981
2982   /* All the subspace dictiondary records are written, and all the
2983      fields are set up in the space dictionary records.
2984
2985      Seek to the right location and start writing the space
2986      dictionary records.  */
2987   location = obj_som_file_hdr (abfd)->space_location;
2988   bfd_seek (abfd, location, SEEK_SET);
2989
2990   section = abfd->sections;
2991   for (i = 0; i < num_spaces; i++)
2992     {
2993
2994       /* Find a space.  */
2995       while (som_section_data (section)->is_space == 0)
2996         section = section->next;
2997
2998       /* Dump its header  */
2999       if (bfd_write ((PTR) &som_section_data (section)->space_dict,
3000                      sizeof (struct space_dictionary_record), 1, abfd)
3001           != sizeof (struct space_dictionary_record))
3002         {
3003           bfd_error = system_call_error;
3004           return false;
3005         }
3006
3007       /* Goto the next section.  */
3008       section = section->next;
3009     }
3010
3011   /* Only thing left to do is write out the file header.  It is always
3012      at location zero.  Seek there and write it.  */
3013   bfd_seek (abfd, (file_ptr) 0, SEEK_SET);
3014   if (bfd_write ((PTR) obj_som_file_hdr (abfd),
3015                  sizeof (struct header), 1, abfd)
3016       != sizeof (struct header))
3017     {
3018       bfd_error = system_call_error;
3019       return false;
3020     }
3021   return true;
3022 }
3023
3024 /* Compute and return the checksum for a SOM file header.  */
3025
3026 static unsigned long
3027 som_compute_checksum (abfd)
3028      bfd *abfd;
3029 {
3030   unsigned long checksum, count, i;
3031   unsigned long *buffer = (unsigned long *) obj_som_file_hdr (abfd);
3032
3033   checksum = 0;
3034   count = sizeof (struct header) / sizeof (unsigned long);
3035   for (i = 0; i < count; i++)
3036     checksum ^= *(buffer + i);
3037
3038   return checksum;
3039 }
3040
3041 /* Build and write, in one big chunk, the entire symbol table for
3042    this BFD.  */
3043
3044 static boolean
3045 som_build_and_write_symbol_table (abfd)
3046      bfd *abfd;
3047 {
3048   unsigned int num_syms = bfd_get_symcount (abfd);
3049   file_ptr symtab_location = obj_som_file_hdr (abfd)->symbol_location;
3050   asymbol **bfd_syms = bfd_get_outsymbols (abfd);
3051   struct symbol_dictionary_record *som_symtab;
3052   int i, symtab_size;
3053
3054   /* Compute total symbol table size and allocate a chunk of memory
3055      to hold the symbol table as we build it.  */
3056   symtab_size = num_syms * sizeof (struct symbol_dictionary_record);
3057   som_symtab = (struct symbol_dictionary_record *) alloca (symtab_size);
3058   bzero (som_symtab, symtab_size);
3059
3060   /* Walk over each symbol.  */
3061   for (i = 0; i < num_syms; i++)
3062     {
3063       /* This is really an index into the symbol strings table.  
3064          By the time we get here, the index has already been 
3065          computed and stored into the name field in the BFD symbol.  */
3066       som_symtab[i].name.n_strx = (int) bfd_syms[i]->name;
3067
3068       /* The HP SOM linker requires detailed type information about
3069          all symbols (including undefined symbols!).  Unfortunately,
3070          the type specified in an import/export statement does not
3071          always match what the linker wants.  Severe braindamage.  */
3072          
3073       /* Section symbols will not have a SOM symbol type assigned to
3074          them yet.  Assign all section symbols type ST_DATA.  */
3075       if (bfd_syms[i]->flags & BSF_SECTION_SYM)
3076         som_symtab[i].symbol_type = ST_DATA;
3077       else
3078         {
3079           /* Common symbols must have scope SS_UNSAT and type
3080              ST_STORAGE or the linker will choke.  */
3081           if (bfd_syms[i]->section == &bfd_com_section)
3082             {
3083               som_symtab[i].symbol_scope = SS_UNSAT;
3084               som_symtab[i].symbol_type = ST_STORAGE;
3085             }
3086
3087           /* It is possible to have a symbol without an associated
3088              type.  This happens if the user imported the symbol
3089              without a type and the symbol was never defined
3090              locally.  If BSF_FUNCTION is set for this symbol, then
3091              assign it type ST_CODE (the HP linker requires undefined
3092              external functions to have type ST_CODE rather than ST_ENTRY.  */
3093           else if (((*som_symbol_data (bfd_syms[i]))->som_type
3094                     == SYMBOL_TYPE_UNKNOWN)
3095                    && (bfd_syms[i]->section == &bfd_und_section)
3096                    && (bfd_syms[i]->flags & BSF_FUNCTION))
3097             som_symtab[i].symbol_type = ST_CODE;
3098
3099           /* Handle function symbols which were defined in this file.
3100              They should have type ST_ENTRY.  Also retrieve the argument
3101              relocation bits from the SOM backend information.  */
3102           else if (((*som_symbol_data (bfd_syms[i]))->som_type
3103                     == SYMBOL_TYPE_ENTRY)
3104                    || (((*som_symbol_data (bfd_syms[i]))->som_type
3105                         == SYMBOL_TYPE_CODE)
3106                        && (bfd_syms[i]->flags & BSF_FUNCTION))
3107                    || (((*som_symbol_data (bfd_syms[i]))->som_type
3108                         == SYMBOL_TYPE_UNKNOWN)
3109                        && (bfd_syms[i]->flags & BSF_FUNCTION)))
3110             {
3111               som_symtab[i].symbol_type = ST_ENTRY;
3112               som_symtab[i].arg_reloc
3113                 = (*som_symbol_data (bfd_syms[i]))->tc_data.hppa_arg_reloc;
3114             }
3115
3116           /* If the type is unknown at this point, it should be
3117              ST_DATA (functions were handled as special cases above).  */
3118           else if ((*som_symbol_data (bfd_syms[i]))->som_type
3119                    == SYMBOL_TYPE_UNKNOWN)
3120             som_symtab[i].symbol_type = ST_DATA;
3121
3122           /* From now on it's a very simple mapping.  */
3123           else if ((*som_symbol_data (bfd_syms[i]))->som_type
3124                    == SYMBOL_TYPE_ABSOLUTE)
3125             som_symtab[i].symbol_type = ST_ABSOLUTE;
3126           else if ((*som_symbol_data (bfd_syms[i]))->som_type
3127                    == SYMBOL_TYPE_CODE)
3128             som_symtab[i].symbol_type = ST_CODE;
3129           else if ((*som_symbol_data (bfd_syms[i]))->som_type
3130                    == SYMBOL_TYPE_DATA)
3131             som_symtab[i].symbol_type = ST_DATA;
3132           else if ((*som_symbol_data (bfd_syms[i]))->som_type
3133                    == SYMBOL_TYPE_MILLICODE)
3134             som_symtab[i].symbol_type = ST_MILLICODE;
3135           else if ((*som_symbol_data (bfd_syms[i]))->som_type
3136                    == SYMBOL_TYPE_PLABEL)
3137             som_symtab[i].symbol_type = ST_PLABEL;
3138           else if ((*som_symbol_data (bfd_syms[i]))->som_type
3139                    == SYMBOL_TYPE_PRI_PROG)
3140             som_symtab[i].symbol_type = ST_PRI_PROG;
3141           else if ((*som_symbol_data (bfd_syms[i]))->som_type
3142                    == SYMBOL_TYPE_SEC_PROG)
3143             som_symtab[i].symbol_type = ST_SEC_PROG;
3144         }
3145         
3146       /* Now handle the symbol's scope.  Exported data which is not
3147          in the common section has scope SS_UNIVERSAL.  Note scope
3148          of common symbols was handled earlier!  */
3149       if (bfd_syms[i]->flags & BSF_EXPORT
3150           && bfd_syms[i]->section != &bfd_com_section)
3151         som_symtab[i].symbol_scope = SS_UNIVERSAL;
3152       /* Any undefined symbol at this point has a scope SS_UNSAT.  */
3153       else if (bfd_syms[i]->section == &bfd_und_section)
3154         som_symtab[i].symbol_scope = SS_UNSAT;
3155       /* Anything else which is not in the common section has scope
3156          SS_LOCAL.  */
3157       else if (bfd_syms[i]->section != &bfd_com_section)
3158         som_symtab[i].symbol_scope = SS_LOCAL;
3159
3160       /* Now set the symbol_info field.  It has no real meaning
3161          for undefined or common symbols, but the HP linker will
3162          choke if it's not set to some "reasonable" value.  We
3163          use zero as a reasonable value.  */
3164       if (bfd_syms[i]->section == &bfd_com_section
3165           || bfd_syms[i]->section == &bfd_und_section)
3166         som_symtab[i].symbol_info = 0;
3167       /* For all other symbols, the symbol_info field contains the 
3168          subspace index of the space this symbol is contained in.  */
3169       else
3170         som_symtab[i].symbol_info
3171           = som_section_data (bfd_syms[i]->section)->subspace_index;
3172
3173       /* Set the symbol's value.  */
3174       som_symtab[i].symbol_value
3175         = bfd_syms[i]->value + bfd_syms[i]->section->vma;
3176     }
3177
3178   /* Egad.  Everything is ready, seek to the right location and
3179      scribble out the symbol table.  */
3180   if (bfd_seek (abfd, symtab_location, SEEK_SET) != 0)
3181     {
3182       bfd_error = system_call_error;
3183       return false;
3184     }
3185
3186   if (bfd_write ((PTR) som_symtab, symtab_size, 1, abfd) != symtab_size)
3187     {
3188       bfd_error  = system_call_error;
3189       return false;
3190     }
3191   return true; 
3192 }
3193
3194 /* Write an object in SOM format.  */  
3195
3196 static boolean
3197 som_write_object_contents (abfd)
3198      bfd *abfd;
3199 {
3200   if (abfd->output_has_begun == false)
3201     {
3202       /* Set up fixed parts of the file, space, and subspace headers.
3203          Notify the world that output has begun.  */
3204       som_prep_headers (abfd);
3205       abfd->output_has_begun = true;
3206       /* Start writing the object file.  This include all the string
3207          tables, fixup streams, and other portions of the object file.  */
3208       som_begin_writing (abfd);
3209     }
3210
3211   /* Now that the symbol table information is complete, build and
3212      write the symbol table.  */
3213   if (som_build_and_write_symbol_table (abfd) == false)
3214     return false;
3215
3216   /* Compute the checksum for the file header just before writing
3217      the header to disk.  */
3218   obj_som_file_hdr (abfd)->checksum = som_compute_checksum (abfd);
3219   return (som_write_headers (abfd));
3220 }
3221
3222 \f
3223 /* Read and save the string table associated with the given BFD.  */
3224
3225 static boolean
3226 som_slurp_string_table (abfd)
3227      bfd *abfd;
3228 {
3229   char *stringtab;
3230
3231   /* Use the saved version if its available.  */
3232   if (obj_som_stringtab (abfd) != NULL)
3233     return true;
3234
3235   /* Allocate and read in the string table.  */
3236   stringtab = bfd_zalloc (abfd, obj_som_stringtab_size (abfd));
3237   if (stringtab == NULL)
3238     {
3239       bfd_error = no_memory;
3240       return false;
3241     }
3242
3243   if (bfd_seek (abfd, obj_som_str_filepos (abfd), SEEK_SET) < 0)
3244     {
3245       bfd_error = system_call_error;
3246       return false;
3247     }
3248   
3249   if (bfd_read (stringtab, obj_som_stringtab_size (abfd), 1, abfd)
3250       != obj_som_stringtab_size (abfd))
3251     {
3252       bfd_error = system_call_error;
3253       return false;
3254     }
3255
3256   /* Save our results and return success. */
3257   obj_som_stringtab (abfd) = stringtab;
3258   return true;
3259 }
3260
3261 /* Return the amount of data (in bytes) required to hold the symbol
3262    table for this object.  */
3263
3264 static unsigned int
3265 som_get_symtab_upper_bound (abfd)
3266      bfd *abfd;
3267 {
3268   if (!som_slurp_symbol_table (abfd))
3269     return 0;
3270
3271   return (bfd_get_symcount (abfd) + 1) * (sizeof (som_symbol_type *));
3272 }
3273
3274 /* Convert from a SOM subspace index to a BFD section.  */
3275
3276 static asection *
3277 som_section_from_subspace_index (abfd, index)
3278      bfd *abfd;
3279      unsigned int index;
3280 {
3281   asection *section;
3282
3283   for (section = abfd->sections; section != NULL; section = section->next)
3284     if (som_section_data (section)->subspace_index == index)
3285       return section;
3286
3287   /* Should never happen.  */
3288   abort();
3289 }
3290
3291 /* Read and save the symbol table associated with the given BFD.  */
3292
3293 static unsigned int
3294 som_slurp_symbol_table (abfd)
3295      bfd *abfd;
3296 {
3297   int symbol_count = bfd_get_symcount (abfd);
3298   int symsize = sizeof (struct symbol_dictionary_record);
3299   char *stringtab;
3300   struct symbol_dictionary_record *buf, *bufp, *endbufp;
3301   som_symbol_type *sym, *symbase;
3302
3303   /* Return saved value if it exists.  */
3304   if (obj_som_symtab (abfd) != NULL)
3305     return true;
3306
3307   /* Sanity checking.  Make sure there are some symbols and that 
3308      we can read the string table too.  */
3309   if (symbol_count == 0)
3310     {
3311       bfd_error = no_symbols;
3312       return false;
3313     }
3314
3315   if (!som_slurp_string_table (abfd))
3316     return false;
3317
3318   stringtab = obj_som_stringtab (abfd);
3319
3320   symbase = (som_symbol_type *)
3321     bfd_zalloc (abfd, symbol_count * sizeof (som_symbol_type));
3322   if (symbase == NULL)
3323     {
3324       bfd_error = no_memory;
3325       return false;
3326     }
3327
3328   /* Read in the external SOM representation.  */
3329   buf = alloca (symbol_count * symsize);
3330   if (buf == NULL)
3331     {
3332       bfd_error = no_memory;
3333       return false;
3334     }
3335   if (bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET) < 0)
3336     {
3337       bfd_error = system_call_error;
3338       return false;
3339     }
3340   if (bfd_read (buf, symbol_count * symsize, 1, abfd) 
3341       != symbol_count * symsize)
3342     {
3343       bfd_error = no_symbols;
3344       return (false);
3345     }
3346
3347   /* Iterate over all the symbols and internalize them.  */
3348   endbufp = buf + symbol_count;
3349   for (bufp = buf, sym = symbase; bufp < endbufp; ++bufp)
3350     {
3351
3352       /* I don't think we care about these.  */
3353       if (bufp->symbol_type == ST_SYM_EXT
3354           || bufp->symbol_type == ST_ARG_EXT)
3355         continue;
3356
3357       /* Some reasonable defaults.  */
3358       sym->symbol.the_bfd = abfd;
3359       sym->symbol.name = bufp->name.n_strx + stringtab;
3360       sym->symbol.value = bufp->symbol_value;
3361       sym->symbol.section = 0;
3362       sym->symbol.flags = 0;
3363
3364       switch (bufp->symbol_type)
3365         {
3366         case ST_ENTRY:
3367         case ST_PRI_PROG:
3368         case ST_SEC_PROG:
3369         case ST_MILLICODE:
3370           sym->symbol.flags |= BSF_FUNCTION;
3371           sym->symbol.value &= ~0x3;
3372           break;
3373
3374         case ST_STUB:
3375         case ST_CODE:
3376           sym->symbol.value &= ~0x3;
3377
3378         default:
3379           break;
3380         }
3381
3382       /* Handle scoping and section information.  */
3383       switch (bufp->symbol_scope)
3384         {
3385         /* symbol_info field is undefined for SS_EXTERNAL and SS_UNSAT symbols,
3386            so the section associated with this symbol can't be known.  */
3387         case SS_EXTERNAL:
3388         case SS_UNSAT:
3389           if (bufp->symbol_type != ST_STORAGE)
3390             sym->symbol.section = &bfd_und_section;
3391           else
3392             sym->symbol.section = &bfd_com_section;
3393           sym->symbol.flags |= (BSF_EXPORT | BSF_GLOBAL);
3394           break;
3395
3396         case SS_UNIVERSAL:
3397           sym->symbol.flags |= (BSF_EXPORT | BSF_GLOBAL);
3398           sym->symbol.section
3399             = som_section_from_subspace_index (abfd, bufp->symbol_info);
3400           sym->symbol.value -= sym->symbol.section->vma;
3401           break;
3402
3403 #if 0
3404         /* SS_GLOBAL and SS_LOCAL are two names for the same thing.
3405            Sound dumb?  It is.  */
3406         case SS_GLOBAL:
3407 #endif
3408         case SS_LOCAL:
3409           sym->symbol.flags |= BSF_LOCAL;
3410           sym->symbol.section
3411             = som_section_from_subspace_index (abfd, bufp->symbol_info);
3412           sym->symbol.value -= sym->symbol.section->vma;
3413           break;
3414         }
3415
3416       /* Mark symbols left around by the debugger.  */
3417       if (strlen (sym->symbol.name) >= 2
3418           && sym->symbol.name[0] == 'L'
3419           && (sym->symbol.name[1] == '$' || sym->symbol.name[2] == '$'
3420               || sym->symbol.name[3] == '$'))
3421         sym->symbol.flags |= BSF_DEBUGGING;
3422
3423       /* Note increment at bottom of loop, since we skip some symbols
3424          we can not include it as part of the for statement.  */
3425       sym++;
3426     }
3427
3428   /* Save our results and return success.  */
3429   obj_som_symtab (abfd) = symbase;
3430   return (true);
3431 }
3432
3433 /* Canonicalize a SOM symbol table.  Return the number of entries
3434    in the symbol table.  */
3435
3436 static unsigned int
3437 som_get_symtab (abfd, location)
3438      bfd *abfd;
3439      asymbol **location;
3440 {
3441   int i;
3442   som_symbol_type *symbase;
3443
3444   if (!som_slurp_symbol_table (abfd))
3445     return 0;
3446
3447   i = bfd_get_symcount (abfd);
3448   symbase = obj_som_symtab (abfd);
3449
3450   for (; i > 0; i--, location++, symbase++)
3451     *location = &symbase->symbol;
3452
3453   /* Final null pointer.  */
3454   *location = 0;
3455   return (bfd_get_symcount (abfd));
3456 }
3457
3458 /* Make a SOM symbol.  There is nothing special to do here.  */
3459
3460 static asymbol *
3461 som_make_empty_symbol (abfd)
3462      bfd *abfd;
3463 {
3464   som_symbol_type *new =
3465   (som_symbol_type *) bfd_zalloc (abfd, sizeof (som_symbol_type));
3466   if (new == NULL)
3467     {
3468       bfd_error = no_memory;
3469       return 0;
3470     }
3471   new->symbol.the_bfd = abfd;
3472
3473   return &new->symbol;
3474 }
3475
3476 /* Print symbol information.  */
3477
3478 static void
3479 som_print_symbol (ignore_abfd, afile, symbol, how)
3480      bfd *ignore_abfd;
3481      PTR afile;
3482      asymbol *symbol;
3483      bfd_print_symbol_type how;
3484 {
3485   FILE *file = (FILE *) afile;
3486   switch (how)
3487     {
3488     case bfd_print_symbol_name:
3489       fprintf (file, "%s", symbol->name);
3490       break;
3491     case bfd_print_symbol_more:
3492       fprintf (file, "som ");
3493       fprintf_vma (file, symbol->value);
3494       fprintf (file, " %lx", (long) symbol->flags);
3495       break;
3496     case bfd_print_symbol_all:
3497       {
3498         CONST char *section_name;
3499         section_name = symbol->section ? symbol->section->name : "(*none*)";
3500         bfd_print_symbol_vandf ((PTR) file, symbol);
3501         fprintf (file, " %s\t%s", section_name, symbol->name);
3502         break;
3503       }
3504     }
3505 }
3506
3507 /* Count or process variable-length SOM fixup records.
3508
3509    To avoid code duplication we use this code both to compute the number
3510    of relocations requested by a stream, and to internalize the stream.
3511
3512    When computing the number of relocations requested by a stream the
3513    variables rptr, section, and symbols have no meaning.
3514
3515    Return the number of relocations requested by the fixup stream.  When
3516    not just counting 
3517
3518    This needs at least two or three more passes to get it cleaned up.  */
3519
3520 static unsigned int
3521 som_set_reloc_info (fixup, end, internal_relocs, section, symbols, just_count)
3522      unsigned char *fixup;
3523      unsigned int end;
3524      arelent *internal_relocs;
3525      asection *section;
3526      asymbol **symbols;
3527      boolean just_count;
3528 {
3529   unsigned int op, varname;
3530   unsigned char *end_fixups = &fixup[end];
3531   const struct fixup_format *fp;
3532   char *cp;
3533   unsigned char *save_fixup;
3534   int variables[26], stack[20], c, v, count, prev_fixup, *sp;
3535   const int *subop;
3536   arelent *rptr= internal_relocs;
3537   unsigned int offset = just_count ? 0 : section->vma;
3538
3539 #define var(c)          variables[(c) - 'A']
3540 #define push(v)         (*sp++ = (v))
3541 #define pop()           (*--sp)
3542 #define emptystack()    (sp == stack)
3543
3544   som_initialize_reloc_queue (reloc_queue);
3545   bzero (variables, sizeof (variables));
3546   bzero (stack, sizeof (stack));
3547   count = 0;
3548   prev_fixup = 0;
3549   sp = stack;
3550
3551   while (fixup < end_fixups)
3552     {
3553
3554       /* Save pointer to the start of this fixup.  We'll use
3555          it later to determine if it is necessary to put this fixup
3556          on the queue.  */
3557       save_fixup = fixup;
3558
3559       /* Get the fixup code and its associated format.  */
3560       op = *fixup++;
3561       fp = &som_fixup_formats[op];
3562
3563       /* Handle a request for a previous fixup.  */
3564       if (*fp->format == 'P')
3565         {
3566           /* Get pointer to the beginning of the prev fixup, move
3567              the repeated fixup to the head of the queue.  */
3568           fixup = reloc_queue[fp->D].reloc;
3569           som_reloc_queue_fix (reloc_queue, fp->D);
3570           prev_fixup = 1;
3571
3572           /* Get the fixup code and its associated format.  */
3573           op = *fixup++;
3574           fp = &som_fixup_formats[op];
3575         }
3576
3577       /* If we are not just counting, set some reasonable defaults.  */
3578       if (! just_count)
3579         {
3580           rptr->address = offset;
3581           rptr->howto = &som_hppa_howto_table[op];
3582           rptr->addend = 0;
3583           rptr->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr;
3584         }
3585
3586       /* Set default input length to 0.  Get the opcode class index
3587          into D.  */
3588       var ('L') = 0;
3589       var ('D') = fp->D;
3590
3591       /* Get the opcode format.  */
3592       cp = fp->format;
3593
3594       /* Process the format string.  Parsing happens in two phases,
3595          parse RHS, then assign to LHS.  Repeat until no more 
3596          characters in the format string.  */
3597       while (*cp)
3598         {
3599           /* The variable this pass is going to compute a value for.  */
3600           varname = *cp++;
3601
3602           /* Start processing RHS.  Continue until a NULL or '=' is found.  */
3603           do
3604             {
3605               c = *cp++;
3606
3607               /* If this is a variable, push it on the stack.  */
3608               if (isupper (c))
3609                 push (var (c));
3610
3611               /* If this is a lower case letter, then it represents
3612                  additional data from the fixup stream to be pushed onto
3613                  the stack.  */
3614               else if (islower (c))
3615                 {
3616                   for (v = 0; c > 'a'; --c)
3617                     v = (v << 8) | *fixup++;
3618                   push (v);
3619                 }
3620
3621               /* A decimal constant.  Push it on the stack.  */
3622               else if (isdigit (c))
3623                 {
3624                   v = c - '0';
3625                   while (isdigit (*cp))
3626                     v = (v * 10) + (*cp++ - '0');
3627                   push (v);
3628                 }
3629               else
3630
3631                 /* An operator.  Pop two two values from the stack and
3632                    use them as operands to the given operation.  Push
3633                    the result of the operation back on the stack.  */
3634                 switch (c)
3635                   {
3636                   case '+':
3637                     v = pop ();
3638                     v += pop ();
3639                     push (v);
3640                     break;
3641                   case '*':
3642                     v = pop ();
3643                     v *= pop ();
3644                     push (v);
3645                     break;
3646                   case '<':
3647                     v = pop ();
3648                     v = pop () << v;
3649                     push (v);
3650                     break;
3651                   default:
3652                     abort ();
3653                   }
3654             }
3655           while (*cp && *cp != '=');
3656
3657           /* Move over the equal operator.  */
3658           cp++;
3659
3660           /* Pop the RHS off the stack.  */
3661           c = pop ();
3662
3663           /* Perform the assignment.  */
3664           var (varname) = c;
3665
3666           /* Handle side effects. and special 'O' stack cases.  */
3667           switch (varname)
3668             {
3669             /* Consume some bytes from the input space.  */
3670             case 'L':
3671               offset += c;
3672               break;
3673             /* A symbol to use in the relocation.  Make a note
3674                of this if we are not just counting.  */
3675             case 'S':
3676               if (! just_count)
3677                 rptr->sym_ptr_ptr = &symbols[c];
3678               break;
3679             /* Handle the linker expression stack.  */
3680             case 'O':
3681               switch (op)
3682                 {
3683                 case R_COMP1:
3684                   subop = comp1_opcodes;
3685                   break;
3686                 case R_COMP2:
3687                   subop = comp2_opcodes;
3688                   break;
3689                 case R_COMP3:
3690                   subop = comp3_opcodes;
3691                   break;
3692                 default:
3693                   abort ();
3694                 }
3695               while (*subop <= (unsigned char) c)
3696                 ++subop;
3697               --subop;
3698               break;
3699             default:
3700               break;
3701             }
3702         }
3703
3704       /* If we used a previous fixup, clean up after it.  */
3705       if (prev_fixup)
3706         {
3707           fixup = save_fixup + 1;
3708           prev_fixup = 0;
3709         }
3710       /* Queue it.  */
3711       else if (fixup > save_fixup + 1)
3712         som_reloc_queue_insert (save_fixup, fixup - save_fixup, reloc_queue);
3713
3714       /* We do not pass R_DATA_OVERRIDE or R_NO_RELOCATION 
3715          fixups to BFD.  */
3716       if (som_hppa_howto_table[op].type != R_DATA_OVERRIDE
3717           && som_hppa_howto_table[op].type != R_NO_RELOCATION)
3718         {
3719           /* Done with a single reloction. Loop back to the top.  */
3720           if (! just_count)
3721             {
3722               rptr->addend = var ('V');
3723               rptr++;
3724             }
3725           count++;
3726           /* Now that we've handled a "full" relocation, reset
3727              some state.  */
3728           bzero (variables, sizeof (variables));
3729           bzero (stack, sizeof (stack));
3730         }
3731     }
3732   return count;
3733
3734 #undef var
3735 #undef push
3736 #undef pop
3737 #undef emptystack
3738 }
3739
3740 /* Read in the relocs (aka fixups in SOM terms) for a section. 
3741
3742    som_get_reloc_upper_bound calls this routine with JUST_COUNT 
3743    set to true to indicate it only needs a count of the number
3744    of actual relocations.  */
3745
3746 static boolean
3747 som_slurp_reloc_table (abfd, section, symbols, just_count)
3748      bfd *abfd;
3749      asection *section;
3750      asymbol **symbols;
3751      boolean just_count;
3752 {
3753   char *external_relocs;
3754   unsigned int fixup_stream_size;
3755   arelent *internal_relocs;
3756   unsigned int num_relocs;
3757
3758   fixup_stream_size = som_section_data (section)->reloc_size;
3759   /* If there were no relocations, then there is nothing to do.  */
3760   if (section->reloc_count == 0)
3761     return true;
3762
3763   /* If reloc_count is -1, then the relocation stream has not been 
3764      parsed.  We must do so now to know how many relocations exist.  */
3765   if (section->reloc_count == -1)
3766     {
3767       external_relocs = (char *) bfd_zalloc (abfd, fixup_stream_size);
3768       if (external_relocs == (char *) NULL)
3769         {
3770           bfd_error = no_memory;
3771           return false;
3772         }
3773       /* Read in the external forms. */
3774       if (bfd_seek (abfd,
3775                     obj_som_reloc_filepos (abfd) + section->rel_filepos,
3776                     SEEK_SET)
3777           != 0)
3778         {
3779           bfd_error = system_call_error;
3780           return false;
3781         }
3782       if (bfd_read (external_relocs, 1, fixup_stream_size, abfd)
3783           != fixup_stream_size)
3784         {
3785           bfd_error = system_call_error;
3786           return false;
3787         }
3788       /* Let callers know how many relocations found.
3789          also save the relocation stream as we will
3790          need it again.  */
3791       section->reloc_count = som_set_reloc_info (external_relocs,
3792                                                  fixup_stream_size,
3793                                                  NULL, NULL, NULL, true);
3794
3795       som_section_data (section)->reloc_stream = external_relocs;
3796     }
3797
3798   /* If the caller only wanted a count, then return now.  */
3799   if (just_count)
3800     return true;
3801
3802   num_relocs = section->reloc_count;
3803   external_relocs = som_section_data (section)->reloc_stream;
3804   /* Return saved information about the relocations if it is available.  */
3805   if (section->relocation != (arelent *) NULL)
3806     return true;
3807
3808   internal_relocs = (arelent *) bfd_zalloc (abfd,
3809                                             num_relocs * sizeof (arelent));
3810   if (internal_relocs == (arelent *) NULL)
3811     {
3812       bfd_error = no_memory;
3813       return false;
3814     }
3815
3816   /* Process and internalize the relocations.  */
3817   som_set_reloc_info (external_relocs, fixup_stream_size,
3818                       internal_relocs, section, symbols, false);
3819
3820   /* Save our results and return success.  */
3821   section->relocation = internal_relocs;
3822   return (true);
3823 }
3824
3825 /* Return the number of bytes required to store the relocation
3826    information associated with the given section.  */ 
3827
3828 static unsigned int
3829 som_get_reloc_upper_bound (abfd, asect)
3830      bfd *abfd;
3831      sec_ptr asect;
3832 {
3833   /* If section has relocations, then read in the relocation stream
3834      and parse it to determine how many relocations exist.  */
3835   if (asect->flags & SEC_RELOC)
3836     {
3837       if (som_slurp_reloc_table (abfd, asect, NULL, true))
3838         return (asect->reloc_count + 1) * sizeof (arelent);
3839     }
3840   /* Either there are no relocations or an error occurred while 
3841      reading and parsing the relocation stream.  */ 
3842   return 0;
3843 }
3844
3845 /* Convert relocations from SOM (external) form into BFD internal
3846    form.  Return the number of relocations.  */
3847
3848 static unsigned int
3849 som_canonicalize_reloc (abfd, section, relptr, symbols)
3850      bfd *abfd;
3851      sec_ptr section;
3852      arelent **relptr;
3853      asymbol **symbols;
3854 {
3855   arelent *tblptr;
3856   int count;
3857
3858   if (som_slurp_reloc_table (abfd, section, symbols, false) == false)
3859     return 0;
3860
3861   count = section->reloc_count;
3862   tblptr = section->relocation;
3863   if (tblptr == (arelent *) NULL)
3864     return 0;
3865
3866   while (count--)
3867     *relptr++ = tblptr++;
3868
3869   *relptr = (arelent *) NULL;
3870   return section->reloc_count;
3871 }
3872
3873 extern bfd_target som_vec;
3874
3875 /* A hook to set up object file dependent section information.  */
3876
3877 static boolean
3878 som_new_section_hook (abfd, newsect)
3879      bfd *abfd;
3880      asection *newsect;
3881 {
3882   newsect->used_by_bfd
3883     = (PTR) bfd_zalloc (abfd, sizeof (struct som_section_data_struct));
3884   newsect->alignment_power = 3;
3885
3886   /* Initialize the subspace_index field to -1 so that it does
3887      not match a subspace with an index of 0.  */
3888   som_section_data (newsect)->subspace_index = -1;
3889
3890   /* We allow more than three sections internally */
3891   return true;
3892 }
3893
3894 /* Set backend info for sections which can not be described
3895    in the BFD data structures.  */
3896
3897 void
3898 bfd_som_set_section_attributes (section, defined, private, sort_key, spnum)
3899      asection *section;
3900      int defined;
3901      int private;
3902      unsigned char sort_key;
3903      int spnum;
3904 {
3905   struct space_dictionary_record *space_dict;
3906
3907   som_section_data (section)->is_space = 1;
3908   space_dict = &som_section_data (section)->space_dict;
3909   space_dict->is_defined = defined;
3910   space_dict->is_private = private;
3911   space_dict->sort_key = sort_key;
3912   space_dict->space_number = spnum;
3913 }
3914
3915 /* Set backend info for subsections which can not be described 
3916    in the BFD data structures.  */
3917
3918 void
3919 bfd_som_set_subsection_attributes (section, container, access,
3920                                    sort_key, quadrant)
3921      asection *section;
3922      asection *container;
3923      int access;
3924      unsigned int sort_key;
3925      int quadrant;
3926 {
3927   struct subspace_dictionary_record *subspace_dict;
3928   som_section_data (section)->is_subspace = 1;
3929   subspace_dict = &som_section_data (section)->subspace_dict;
3930   subspace_dict->access_control_bits = access;
3931   subspace_dict->sort_key = sort_key;
3932   subspace_dict->quadrant = quadrant;
3933   som_section_data (section)->containing_space = container;
3934 }
3935
3936 /* Set the full SOM symbol type.  SOM needs far more symbol information
3937    than any other object file format I'm aware of.  It is mandatory
3938    to be able to know if a symbol is an entry point, millicode, data,
3939    code, absolute, storage request, or procedure label.  If you get
3940    the symbol type wrong your program will not link.  */
3941
3942 void
3943 bfd_som_set_symbol_type (symbol, type)
3944      asymbol *symbol;
3945      unsigned int type;
3946 {
3947   (*som_symbol_data (symbol))->som_type = type;
3948 }
3949
3950 /* Attach 64bits of unwind information to a symbol (which hopefully
3951    is a function of some kind!).  It would be better to keep this
3952    in the R_ENTRY relocation, but there is not enough space.  */
3953
3954 void
3955 bfd_som_attach_unwind_info (symbol, unwind_desc)
3956      asymbol *symbol;
3957      char *unwind_desc;
3958 {
3959   (*som_symbol_data (symbol))->unwind = unwind_desc;
3960 }
3961
3962 /* Attach an auxiliary header to the BFD backend so that it may be
3963    written into the object file.  */
3964 void
3965 bfd_som_attach_aux_hdr (abfd, type, string)
3966      bfd *abfd;
3967      int type;
3968      char *string;
3969 {
3970   if (type == VERSION_AUX_ID)
3971     {
3972       int len = strlen (string);
3973       int pad = 0;
3974
3975       if (len % 4)
3976         pad = (4 - (len % 4));
3977       obj_som_version_hdr (abfd) = (struct user_string_aux_hdr *)
3978         bfd_zalloc (abfd, sizeof (struct aux_id)
3979                             + sizeof (unsigned int) + len + pad);
3980       obj_som_version_hdr (abfd)->header_id.type = VERSION_AUX_ID;
3981       obj_som_version_hdr (abfd)->header_id.length = len + pad;
3982       obj_som_version_hdr (abfd)->header_id.length += sizeof (int);
3983       obj_som_version_hdr (abfd)->string_length = len;
3984       strncpy (obj_som_version_hdr (abfd)->user_string, string, len);
3985     }
3986   else if (type == COPYRIGHT_AUX_ID)
3987     {
3988       int len = strlen (string);
3989       int pad = 0;
3990
3991       if (len % 4)
3992         pad = (4 - (len % 4));
3993       obj_som_copyright_hdr (abfd) = (struct copyright_aux_hdr *)
3994         bfd_zalloc (abfd, sizeof (struct aux_id)
3995                             + sizeof (unsigned int) + len + pad);
3996       obj_som_copyright_hdr (abfd)->header_id.type = COPYRIGHT_AUX_ID;
3997       obj_som_copyright_hdr (abfd)->header_id.length = len + pad;
3998       obj_som_copyright_hdr (abfd)->header_id.length += sizeof (int);
3999       obj_som_copyright_hdr (abfd)->string_length = len;
4000       strcpy (obj_som_copyright_hdr (abfd)->copyright, string);
4001     }
4002   else
4003     abort ();
4004 }
4005
4006 static boolean
4007 som_set_section_contents (abfd, section, location, offset, count)
4008      bfd *abfd;
4009      sec_ptr section;
4010      PTR location;
4011      file_ptr offset;
4012      bfd_size_type count;
4013 {
4014   if (abfd->output_has_begun == false)
4015     {
4016       /* Set up fixed parts of the file, space, and subspace headers.
4017          Notify the world that output has begun.  */
4018       som_prep_headers (abfd);
4019       abfd->output_has_begun = true;
4020       /* Start writing the object file.  This include all the string
4021          tables, fixup streams, and other portions of the object file.  */
4022       som_begin_writing (abfd);
4023     }
4024
4025   /* Only write subspaces which have "real" contents (eg. the contents
4026      are not generated at run time by the OS).  */
4027   if (som_section_data (section)->is_subspace != 1
4028       || ((section->flags & (SEC_LOAD | SEC_DEBUGGING)) == 0))
4029     return true;
4030
4031   /* Seek to the proper offset within the object file and write the
4032      data.  */
4033   offset += som_section_data (section)->subspace_dict.file_loc_init_value; 
4034   if (bfd_seek (abfd, offset, SEEK_SET) == -1)
4035     {
4036       bfd_error = system_call_error;
4037       return false;
4038     }
4039
4040   if (bfd_write ((PTR) location, 1, count, abfd) != count)
4041     {
4042       bfd_error = system_call_error;
4043       return false;
4044     }
4045   return true;
4046 }
4047
4048 static boolean
4049 som_set_arch_mach (abfd, arch, machine)
4050      bfd *abfd;
4051      enum bfd_architecture arch;
4052      unsigned long machine;
4053 {
4054   /* Allow any architecture to be supported by the SOM backend */
4055   return bfd_default_set_arch_mach (abfd, arch, machine);
4056 }
4057
4058 static boolean
4059 som_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
4060                         functionname_ptr, line_ptr)
4061      bfd *abfd;
4062      asection *section;
4063      asymbol **symbols;
4064      bfd_vma offset;
4065      CONST char **filename_ptr;
4066      CONST char **functionname_ptr;
4067      unsigned int *line_ptr;
4068 {
4069   fprintf (stderr, "som_find_nearest_line unimplemented\n");
4070   fflush (stderr);
4071   abort ();
4072   return (false);
4073 }
4074
4075 static int
4076 som_sizeof_headers (abfd, reloc)
4077      bfd *abfd;
4078      boolean reloc;
4079 {
4080   fprintf (stderr, "som_sizeof_headers unimplemented\n");
4081   fflush (stderr);
4082   abort ();
4083   return (0);
4084 }
4085
4086 /* Return the single-character symbol type corresponding to
4087    SOM section S, or '?' for an unknown SOM section.  */
4088
4089 static char
4090 som_section_type (s)
4091      const char *s;
4092 {
4093   const struct section_to_type *t;
4094
4095   for (t = &stt[0]; t->section; t++)
4096     if (!strcmp (s, t->section))
4097       return t->type;
4098   return '?';
4099 }
4100
4101 static int
4102 som_decode_symclass (symbol)
4103      asymbol *symbol;
4104 {
4105   char c;
4106
4107   if (bfd_is_com_section (symbol->section))
4108     return 'C';
4109   if (symbol->section == &bfd_und_section)
4110     return 'U';
4111   if (symbol->section == &bfd_ind_section)
4112     return 'I';
4113   if (!(symbol->flags & (BSF_GLOBAL|BSF_LOCAL)))
4114     return '?';
4115
4116   if (symbol->section == &bfd_abs_section)
4117     c = 'a';
4118   else if (symbol->section)
4119     c = som_section_type (symbol->section->name);
4120   else
4121     return '?';
4122   if (symbol->flags & BSF_GLOBAL)
4123     c = toupper (c);
4124   return c;
4125 }
4126
4127 /* Return information about SOM symbol SYMBOL in RET.  */
4128
4129 static void
4130 som_get_symbol_info (ignore_abfd, symbol, ret)
4131      bfd *ignore_abfd;
4132      asymbol *symbol;
4133      symbol_info *ret;
4134 {
4135   ret->type = som_decode_symclass (symbol);
4136   if (ret->type != 'U')
4137     ret->value = symbol->value+symbol->section->vma;
4138   else
4139     ret->value = 0;
4140   ret->name = symbol->name;
4141 }
4142
4143 /* End of miscellaneous support functions. */
4144
4145 #define som_bfd_debug_info_start        bfd_void
4146 #define som_bfd_debug_info_end          bfd_void
4147 #define som_bfd_debug_info_accumulate   (PROTO(void,(*),(bfd*, struct sec *))) bfd_void
4148
4149 #define som_openr_next_archived_file    bfd_generic_openr_next_archived_file
4150 #define som_generic_stat_arch_elt       bfd_generic_stat_arch_elt
4151 #define som_slurp_armap                  bfd_false
4152 #define som_slurp_extended_name_table    _bfd_slurp_extended_name_table
4153 #define som_truncate_arname              (void (*)())bfd_nullvoidptr
4154 #define som_write_armap                  0
4155
4156 #define som_get_lineno                   (struct lineno_cache_entry *(*)())bfd_nullvoidptr
4157 #define som_close_and_cleanup              bfd_generic_close_and_cleanup
4158 #define som_get_section_contents          bfd_generic_get_section_contents
4159
4160 #define som_bfd_get_relocated_section_contents \
4161  bfd_generic_get_relocated_section_contents
4162 #define som_bfd_relax_section bfd_generic_relax_section
4163 #define som_bfd_make_debug_symbol \
4164   ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr)
4165 #define som_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
4166 #define som_bfd_link_add_symbols _bfd_generic_link_add_symbols
4167 #define som_bfd_final_link _bfd_generic_final_link
4168
4169 /* Core file support is in the hpux-core backend.  */
4170 #define som_core_file_failing_command   _bfd_dummy_core_file_failing_command
4171 #define som_core_file_failing_signal    _bfd_dummy_core_file_failing_signal
4172 #define som_core_file_matches_executable_p      _bfd_dummy_core_file_matches_executable_p
4173
4174 bfd_target som_vec =
4175 {
4176   "som",                        /* name */
4177   bfd_target_som_flavour,
4178   true,                         /* target byte order */
4179   true,                         /* target headers byte order */
4180   (HAS_RELOC | EXEC_P |         /* object flags */
4181    HAS_LINENO | HAS_DEBUG |
4182    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
4183   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
4184    | SEC_ALLOC | SEC_LOAD | SEC_RELOC),         /* section flags */
4185
4186 /* leading_symbol_char: is the first char of a user symbol
4187    predictable, and if so what is it */
4188   0,
4189   ' ',                          /* ar_pad_char */
4190   16,                           /* ar_max_namelen */
4191   3,                            /* minimum alignment */
4192   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
4193   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
4194   bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* data */
4195   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
4196   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
4197   bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* hdrs */
4198   {_bfd_dummy_target,
4199    som_object_p,                /* bfd_check_format */
4200    bfd_generic_archive_p,
4201    _bfd_dummy_target
4202   },
4203   {
4204     bfd_false,
4205     som_mkobject,
4206     _bfd_generic_mkarchive,
4207     bfd_false
4208   },
4209   {
4210     bfd_false,
4211     som_write_object_contents,
4212     _bfd_write_archive_contents,
4213     bfd_false,
4214   },
4215 #undef som
4216   JUMP_TABLE (som),
4217   (PTR) 0
4218 };
4219
4220 #endif /* HOST_HPPAHPUX || HOST_HPPABSD || HOST_HPPAOSF */
This page took 0.254374 seconds and 4 git commands to generate.