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