OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [bfd/] [som.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.