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

Subversion Repositories or1k

[/] [or1k/] [tags/] [VER_5_3/] [gdb-5.3/] [bfd/] [som.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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