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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [bfd/] [som.c] - Blame information for rev 161

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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