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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-7.2/] [bfd/] [som.c] - Blame information for rev 474

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 330 jeremybenn
/* 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
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
  fflush (stderr);
5778
  abort ();
5779
  return 0;
5780
}
5781
 
5782
/* Return the single-character symbol type corresponding to
5783
   SOM section S, or '?' for an unknown SOM section.  */
5784
 
5785
static char
5786
som_section_type (const char *s)
5787
{
5788
  const struct section_to_type *t;
5789
 
5790
  for (t = &stt[0]; t->section; t++)
5791
    if (!strcmp (s, t->section))
5792
      return t->type;
5793
  return '?';
5794
}
5795
 
5796
static int
5797
som_decode_symclass (asymbol *symbol)
5798
{
5799
  char c;
5800
 
5801
  if (bfd_is_com_section (symbol->section))
5802
    return 'C';
5803
  if (bfd_is_und_section (symbol->section))
5804
    {
5805
      if (symbol->flags & BSF_WEAK)
5806
        {
5807
          /* If weak, determine if it's specifically an object
5808
             or non-object weak.  */
5809
          if (symbol->flags & BSF_OBJECT)
5810
            return 'v';
5811
          else
5812
            return 'w';
5813
        }
5814
      else
5815
         return 'U';
5816
    }
5817
  if (bfd_is_ind_section (symbol->section))
5818
    return 'I';
5819
  if (symbol->flags & BSF_WEAK)
5820
    {
5821
      /* If weak, determine if it's specifically an object
5822
         or non-object weak.  */
5823
      if (symbol->flags & BSF_OBJECT)
5824
        return 'V';
5825
      else
5826
        return 'W';
5827
    }
5828
  if (!(symbol->flags & (BSF_GLOBAL | BSF_LOCAL)))
5829
    return '?';
5830
 
5831
  if (bfd_is_abs_section (symbol->section)
5832
      || (som_symbol_data (symbol) != NULL
5833
          && som_symbol_data (symbol)->som_type == SYMBOL_TYPE_ABSOLUTE))
5834
    c = 'a';
5835
  else if (symbol->section)
5836
    c = som_section_type (symbol->section->name);
5837
  else
5838
    return '?';
5839
  if (symbol->flags & BSF_GLOBAL)
5840
    c = TOUPPER (c);
5841
  return c;
5842
}
5843
 
5844
/* Return information about SOM symbol SYMBOL in RET.  */
5845
 
5846
static void
5847
som_get_symbol_info (bfd *ignore_abfd ATTRIBUTE_UNUSED,
5848
                     asymbol *symbol,
5849
                     symbol_info *ret)
5850
{
5851
  ret->type = som_decode_symclass (symbol);
5852
  if (ret->type != 'U')
5853
    ret->value = symbol->value + symbol->section->vma;
5854
  else
5855
    ret->value = 0;
5856
  ret->name = symbol->name;
5857
}
5858
 
5859
/* Count the number of symbols in the archive symbol table.  Necessary
5860
   so that we can allocate space for all the carsyms at once.  */
5861
 
5862
static bfd_boolean
5863
som_bfd_count_ar_symbols (bfd *abfd,
5864
                          struct som_lst_header *lst_header,
5865
                          symindex *count)
5866
{
5867
  unsigned int i;
5868
  unsigned char *hash_table;
5869
  bfd_size_type amt;
5870
  file_ptr lst_filepos;
5871
 
5872
  lst_filepos = bfd_tell (abfd) - sizeof (struct som_external_lst_header);
5873
 
5874
  amt = lst_header->hash_size * 4;
5875
  hash_table = bfd_malloc (amt);
5876
  if (hash_table == NULL && amt != 0)
5877
    goto error_return;
5878
 
5879
  /* Don't forget to initialize the counter!  */
5880
  *count = 0;
5881
 
5882
  /* Read in the hash table.  The has table is an array of 32bit file offsets
5883
     which point to the hash chains.  */
5884
  if (bfd_bread ((void *) hash_table, amt, abfd) != amt)
5885
    goto error_return;
5886
 
5887
  /* Walk each chain counting the number of symbols found on that particular
5888
     chain.  */
5889
  for (i = 0; i < lst_header->hash_size; i++)
5890
    {
5891
      struct som_external_lst_symbol_record ext_lst_symbol;
5892
      unsigned int hash_val = bfd_getb32 (hash_table + 4 * i);
5893
 
5894
      /* An empty chain has zero as it's file offset.  */
5895
      if (hash_val == 0)
5896
        continue;
5897
 
5898
      /* Seek to the first symbol in this hash chain.  */
5899
      if (bfd_seek (abfd, lst_filepos + hash_val, SEEK_SET) != 0)
5900
        goto error_return;
5901
 
5902
      /* Read in this symbol and update the counter.  */
5903
      amt = sizeof (ext_lst_symbol);
5904
      if (bfd_bread ((void *) &ext_lst_symbol, amt, abfd) != amt)
5905
        goto error_return;
5906
 
5907
      (*count)++;
5908
 
5909
      /* Now iterate through the rest of the symbols on this chain.  */
5910
      while (1)
5911
        {
5912
          unsigned int next_entry = bfd_getb32 (ext_lst_symbol.next_entry);
5913
 
5914
          if (next_entry == 0)
5915
            break;
5916
 
5917
          /* Seek to the next symbol.  */
5918
          if (bfd_seek (abfd, lst_filepos + next_entry, SEEK_SET) != 0)
5919
            goto error_return;
5920
 
5921
          /* Read the symbol in and update the counter.  */
5922
          amt = sizeof (ext_lst_symbol);
5923
          if (bfd_bread ((void *) &ext_lst_symbol, amt, abfd) != amt)
5924
            goto error_return;
5925
 
5926
          (*count)++;
5927
        }
5928
    }
5929
  if (hash_table != NULL)
5930
    free (hash_table);
5931
  return TRUE;
5932
 
5933
 error_return:
5934
  if (hash_table != NULL)
5935
    free (hash_table);
5936
  return FALSE;
5937
}
5938
 
5939
/* Fill in the canonical archive symbols (SYMS) from the archive described
5940
   by ABFD and LST_HEADER.  */
5941
 
5942
static bfd_boolean
5943
som_bfd_fill_in_ar_symbols (bfd *abfd,
5944
                            struct som_lst_header *lst_header,
5945
                            carsym **syms)
5946
{
5947
  unsigned int i;
5948
  carsym *set = syms[0];
5949
  unsigned char *hash_table;
5950
  struct som_external_som_entry *som_dict = NULL;
5951
  bfd_size_type amt;
5952
  file_ptr lst_filepos;
5953
  unsigned int string_loc;
5954
 
5955
  lst_filepos = bfd_tell (abfd) - sizeof (struct som_external_lst_header);
5956
  amt = lst_header->hash_size * 4;
5957
  hash_table = bfd_malloc (amt);
5958
  if (hash_table == NULL && amt != 0)
5959
    goto error_return;
5960
 
5961
  /* Read in the hash table.  The has table is an array of 32bit file offsets
5962
     which point to the hash chains.  */
5963
  if (bfd_bread ((void *) hash_table, amt, abfd) != amt)
5964
    goto error_return;
5965
 
5966
  /* Seek to and read in the SOM dictionary.  We will need this to fill
5967
     in the carsym's filepos field.  */
5968
  if (bfd_seek (abfd, lst_filepos + lst_header->dir_loc, SEEK_SET) != 0)
5969
    goto error_return;
5970
 
5971
  amt = lst_header->module_count * sizeof (struct som_external_som_entry);
5972
  som_dict = bfd_malloc (amt);
5973
  if (som_dict == NULL && amt != 0)
5974
    goto error_return;
5975
 
5976
  if (bfd_bread ((void *) som_dict, amt, abfd) != amt)
5977
    goto error_return;
5978
 
5979
  string_loc = lst_header->string_loc;
5980
 
5981
  /* Walk each chain filling in the carsyms as we go along.  */
5982
  for (i = 0; i < lst_header->hash_size; i++)
5983
    {
5984
      struct som_external_lst_symbol_record lst_symbol;
5985
      unsigned int hash_val;
5986
      unsigned int len;
5987
      unsigned char ext_len[4];
5988
 
5989
      /* An empty chain has zero as it's file offset.  */
5990
      hash_val = bfd_getb32 (hash_table + 4 * i);
5991
      if (hash_val == 0)
5992
        continue;
5993
 
5994
      /* Seek to and read the first symbol on the chain.  */
5995
      if (bfd_seek (abfd, lst_filepos + hash_val, SEEK_SET) != 0)
5996
        goto error_return;
5997
 
5998
      amt = sizeof (lst_symbol);
5999
      if (bfd_bread ((void *) &lst_symbol, amt, abfd) != amt)
6000
        goto error_return;
6001
 
6002
      /* Get the name of the symbol, first get the length which is stored
6003
         as a 32bit integer just before the symbol.
6004
 
6005
         One might ask why we don't just read in the entire string table
6006
         and index into it.  Well, according to the SOM ABI the string
6007
         index can point *anywhere* in the archive to save space, so just
6008
         using the string table would not be safe.  */
6009
      if (bfd_seek (abfd, (lst_filepos + string_loc
6010
                           + bfd_getb32 (lst_symbol.name) - 4), SEEK_SET) != 0)
6011
        goto error_return;
6012
 
6013
      if (bfd_bread (&ext_len, (bfd_size_type) 4, abfd) != 4)
6014
        goto error_return;
6015
      len = bfd_getb32 (ext_len);
6016
 
6017
      /* Allocate space for the name and null terminate it too.  */
6018
      set->name = bfd_zalloc (abfd, (bfd_size_type) len + 1);
6019
      if (!set->name)
6020
        goto error_return;
6021
      if (bfd_bread (set->name, (bfd_size_type) len, abfd) != len)
6022
        goto error_return;
6023
 
6024
      set->name[len] = 0;
6025
 
6026
      /* Fill in the file offset.  Note that the "location" field points
6027
         to the SOM itself, not the ar_hdr in front of it.  */
6028
      set->file_offset =
6029
        bfd_getb32 (som_dict[bfd_getb32 (lst_symbol.som_index)].location)
6030
        - sizeof (struct ar_hdr);
6031
 
6032
      /* Go to the next symbol.  */
6033
      set++;
6034
 
6035
      /* Iterate through the rest of the chain.  */
6036
      while (1)
6037
        {
6038
          unsigned int next_entry = bfd_getb32 (lst_symbol.next_entry);
6039
 
6040
          if (next_entry == 0)
6041
            break;
6042
 
6043
          /* Seek to the next symbol and read it in.  */
6044
          if (bfd_seek (abfd, lst_filepos + next_entry, SEEK_SET) != 0)
6045
            goto error_return;
6046
 
6047
          amt = sizeof (lst_symbol);
6048
          if (bfd_bread ((void *) &lst_symbol, amt, abfd) != amt)
6049
            goto error_return;
6050
 
6051
          /* Seek to the name length & string and read them in.  */
6052
          if (bfd_seek (abfd, lst_filepos + string_loc
6053
                        + bfd_getb32 (lst_symbol.name) - 4, SEEK_SET) != 0)
6054
            goto error_return;
6055
 
6056
          if (bfd_bread (&ext_len, (bfd_size_type) 4, abfd) != 4)
6057
            goto error_return;
6058
          len = bfd_getb32 (ext_len);
6059
 
6060
          /* Allocate space for the name and null terminate it too.  */
6061
          set->name = bfd_zalloc (abfd, (bfd_size_type) len + 1);
6062
          if (!set->name)
6063
            goto error_return;
6064
 
6065
          if (bfd_bread (set->name, (bfd_size_type) len, abfd) != len)
6066
            goto error_return;
6067
          set->name[len] = 0;
6068
 
6069
          /* Fill in the file offset.  Note that the "location" field points
6070
             to the SOM itself, not the ar_hdr in front of it.  */
6071
          set->file_offset =
6072
            bfd_getb32 (som_dict[bfd_getb32 (lst_symbol.som_index)].location)
6073
            - sizeof (struct ar_hdr);
6074
 
6075
          /* Go on to the next symbol.  */
6076
          set++;
6077
        }
6078
    }
6079
  /* If we haven't died by now, then we successfully read the entire
6080
     archive symbol table.  */
6081
  if (hash_table != NULL)
6082
    free (hash_table);
6083
  if (som_dict != NULL)
6084
    free (som_dict);
6085
  return TRUE;
6086
 
6087
 error_return:
6088
  if (hash_table != NULL)
6089
    free (hash_table);
6090
  if (som_dict != NULL)
6091
    free (som_dict);
6092
  return FALSE;
6093
}
6094
 
6095
/* Read in the LST from the archive.  */
6096
 
6097
static bfd_boolean
6098
som_slurp_armap (bfd *abfd)
6099
{
6100
  struct som_external_lst_header ext_lst_header;
6101
  struct som_lst_header lst_header;
6102
  struct ar_hdr ar_header;
6103
  unsigned int parsed_size;
6104
  struct artdata *ardata = bfd_ardata (abfd);
6105
  char nextname[17];
6106
  bfd_size_type amt = 16;
6107
  int i = bfd_bread ((void *) nextname, amt, abfd);
6108
 
6109
  /* Special cases.  */
6110
  if (i == 0)
6111
    return TRUE;
6112
  if (i != 16)
6113
    return FALSE;
6114
 
6115
  if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
6116
    return FALSE;
6117
 
6118
  /* For archives without .o files there is no symbol table.  */
6119
  if (! CONST_STRNEQ (nextname, "/               "))
6120
    {
6121
      bfd_has_map (abfd) = FALSE;
6122
      return TRUE;
6123
    }
6124
 
6125
  /* Read in and sanity check the archive header.  */
6126
  amt = sizeof (struct ar_hdr);
6127
  if (bfd_bread ((void *) &ar_header, amt, abfd) != amt)
6128
    return FALSE;
6129
 
6130
  if (strncmp (ar_header.ar_fmag, ARFMAG, 2))
6131
    {
6132
      bfd_set_error (bfd_error_malformed_archive);
6133
      return FALSE;
6134
    }
6135
 
6136
  /* How big is the archive symbol table entry?  */
6137
  errno = 0;
6138
  parsed_size = strtol (ar_header.ar_size, NULL, 10);
6139
  if (errno != 0)
6140
    {
6141
      bfd_set_error (bfd_error_malformed_archive);
6142
      return FALSE;
6143
    }
6144
 
6145
  /* Save off the file offset of the first real user data.  */
6146
  ardata->first_file_filepos = bfd_tell (abfd) + parsed_size;
6147
 
6148
  /* Read in the library symbol table.  We'll make heavy use of this
6149
     in just a minute.  */
6150
  amt = sizeof (struct som_external_lst_header);
6151
  if (bfd_bread ((void *) &ext_lst_header, amt, abfd) != amt)
6152
    return FALSE;
6153
 
6154
  som_swap_lst_header_in (&ext_lst_header, &lst_header);
6155
 
6156
  /* Sanity check.  */
6157
  if (lst_header.a_magic != LIBMAGIC)
6158
    {
6159
      bfd_set_error (bfd_error_malformed_archive);
6160
      return FALSE;
6161
    }
6162
 
6163
  /* Count the number of symbols in the library symbol table.  */
6164
  if (! som_bfd_count_ar_symbols (abfd, &lst_header, &ardata->symdef_count))
6165
    return FALSE;
6166
 
6167
  /* Get back to the start of the library symbol table.  */
6168
  if (bfd_seek (abfd, (ardata->first_file_filepos - parsed_size
6169
                       + sizeof (struct som_external_lst_header)),
6170
                SEEK_SET) != 0)
6171
    return FALSE;
6172
 
6173
  /* Initialize the cache and allocate space for the library symbols.  */
6174
  ardata->cache = 0;
6175
  amt = ardata->symdef_count;
6176
  amt *= sizeof (carsym);
6177
  ardata->symdefs = bfd_alloc (abfd, amt);
6178
  if (!ardata->symdefs)
6179
    return FALSE;
6180
 
6181
  /* Now fill in the canonical archive symbols.  */
6182
  if (! som_bfd_fill_in_ar_symbols (abfd, &lst_header, &ardata->symdefs))
6183
    return FALSE;
6184
 
6185
  /* Seek back to the "first" file in the archive.  Note the "first"
6186
     file may be the extended name table.  */
6187
  if (bfd_seek (abfd, ardata->first_file_filepos, SEEK_SET) != 0)
6188
    return FALSE;
6189
 
6190
  /* Notify the generic archive code that we have a symbol map.  */
6191
  bfd_has_map (abfd) = TRUE;
6192
  return TRUE;
6193
}
6194
 
6195
/* Begin preparing to write a SOM library symbol table.
6196
 
6197
   As part of the prep work we need to determine the number of symbols
6198
   and the size of the associated string section.  */
6199
 
6200
static bfd_boolean
6201
som_bfd_prep_for_ar_write (bfd *abfd,
6202
                           unsigned int *num_syms,
6203
                           unsigned int *stringsize)
6204
{
6205
  bfd *curr_bfd = abfd->archive_head;
6206
 
6207
  /* Some initialization.  */
6208
  *num_syms = 0;
6209
  *stringsize = 0;
6210
 
6211
  /* Iterate over each BFD within this archive.  */
6212
  while (curr_bfd != NULL)
6213
    {
6214
      unsigned int curr_count, i;
6215
      som_symbol_type *sym;
6216
 
6217
      /* Don't bother for non-SOM objects.  */
6218
      if (curr_bfd->format != bfd_object
6219
          || curr_bfd->xvec->flavour != bfd_target_som_flavour)
6220
        {
6221
          curr_bfd = curr_bfd->archive_next;
6222
          continue;
6223
        }
6224
 
6225
      /* Make sure the symbol table has been read, then snag a pointer
6226
         to it.  It's a little slimey to grab the symbols via obj_som_symtab,
6227
         but doing so avoids allocating lots of extra memory.  */
6228
      if (! som_slurp_symbol_table (curr_bfd))
6229
        return FALSE;
6230
 
6231
      sym = obj_som_symtab (curr_bfd);
6232
      curr_count = bfd_get_symcount (curr_bfd);
6233
 
6234
      /* Examine each symbol to determine if it belongs in the
6235
         library symbol table.  */
6236
      for (i = 0; i < curr_count; i++, sym++)
6237
        {
6238
          struct som_misc_symbol_info info;
6239
 
6240
          /* Derive SOM information from the BFD symbol.  */
6241
          som_bfd_derive_misc_symbol_info (curr_bfd, &sym->symbol, &info);
6242
 
6243
          /* Should we include this symbol?  */
6244
          if (info.symbol_type == ST_NULL
6245
              || info.symbol_type == ST_SYM_EXT
6246
              || info.symbol_type == ST_ARG_EXT)
6247
            continue;
6248
 
6249
          /* Only global symbols and unsatisfied commons.  */
6250
          if (info.symbol_scope != SS_UNIVERSAL
6251
              && info.symbol_type != ST_STORAGE)
6252
            continue;
6253
 
6254
          /* Do no include undefined symbols.  */
6255
          if (bfd_is_und_section (sym->symbol.section))
6256
            continue;
6257
 
6258
          /* Bump the various counters, being careful to honor
6259
             alignment considerations in the string table.  */
6260
          (*num_syms)++;
6261
          *stringsize += strlen (sym->symbol.name) + 5;
6262
          while (*stringsize % 4)
6263
            (*stringsize)++;
6264
        }
6265
 
6266
      curr_bfd = curr_bfd->archive_next;
6267
    }
6268
  return TRUE;
6269
}
6270
 
6271
/* Hash a symbol name based on the hashing algorithm presented in the
6272
   SOM ABI.  */
6273
 
6274
static unsigned int
6275
som_bfd_ar_symbol_hash (asymbol *symbol)
6276
{
6277
  unsigned int len = strlen (symbol->name);
6278
 
6279
  /* Names with length 1 are special.  */
6280
  if (len == 1)
6281
    return 0x1000100 | (symbol->name[0] << 16) | symbol->name[0];
6282
 
6283
  return ((len & 0x7f) << 24) | (symbol->name[1] << 16)
6284
          | (symbol->name[len - 2] << 8) | symbol->name[len - 1];
6285
}
6286
 
6287
/* Do the bulk of the work required to write the SOM library
6288
   symbol table.  */
6289
 
6290
static bfd_boolean
6291
som_bfd_ar_write_symbol_stuff (bfd *abfd,
6292
                               unsigned int nsyms,
6293
                               unsigned int string_size,
6294
                               struct som_external_lst_header lst,
6295
                               unsigned elength)
6296
{
6297
  char *strings = NULL, *p;
6298
  struct som_external_lst_symbol_record *lst_syms = NULL, *curr_lst_sym;
6299
  bfd *curr_bfd;
6300
  unsigned char *hash_table = NULL;
6301
  struct som_external_som_entry *som_dict = NULL;
6302
  struct som_external_lst_symbol_record **last_hash_entry = NULL;
6303
  unsigned int curr_som_offset, som_index = 0;
6304
  bfd_size_type amt;
6305
  unsigned int module_count;
6306
  unsigned int hash_size;
6307
 
6308
  hash_size = bfd_getb32 (lst.hash_size);
6309
  amt = hash_size * 4;
6310
  hash_table = bfd_zmalloc (amt);
6311
  if (hash_table == NULL && hash_size != 0)
6312
    goto error_return;
6313
 
6314
  module_count = bfd_getb32 (lst.module_count);
6315
  amt = module_count * sizeof (struct som_external_som_entry);
6316
  som_dict = bfd_zmalloc (amt);
6317
  if (som_dict == NULL && module_count != 0)
6318
    goto error_return;
6319
 
6320
  amt = hash_size * sizeof (struct som_external_lst_symbol_record *);
6321
  last_hash_entry = bfd_zmalloc (amt);
6322
  if (last_hash_entry == NULL && hash_size != 0)
6323
    goto error_return;
6324
 
6325
  /* Symbols have som_index fields, so we have to keep track of the
6326
     index of each SOM in the archive.
6327
 
6328
     The SOM dictionary has (among other things) the absolute file
6329
     position for the SOM which a particular dictionary entry
6330
     describes.  We have to compute that information as we iterate
6331
     through the SOMs/symbols.  */
6332
  som_index = 0;
6333
 
6334
  /* We add in the size of the archive header twice as the location
6335
     in the SOM dictionary is the actual offset of the SOM, not the
6336
     archive header before the SOM.  */
6337
  curr_som_offset = 8 + 2 * sizeof (struct ar_hdr) + bfd_getb32 (lst.file_end);
6338
 
6339
  /* Make room for the archive header and the contents of the
6340
     extended string table.  Note that elength includes the size
6341
     of the archive header for the extended name table!  */
6342
  if (elength)
6343
    curr_som_offset += elength;
6344
 
6345
  /* Make sure we're properly aligned.  */
6346
  curr_som_offset = (curr_som_offset + 0x1) & ~0x1;
6347
 
6348
  /* FIXME should be done with buffers just like everything else...  */
6349
  amt = nsyms;
6350
  amt *= sizeof (struct som_external_lst_symbol_record);
6351
  lst_syms = bfd_malloc (amt);
6352
  if (lst_syms == NULL && nsyms != 0)
6353
    goto error_return;
6354
  strings = bfd_malloc ((bfd_size_type) string_size);
6355
  if (strings == NULL && string_size != 0)
6356
    goto error_return;
6357
 
6358
  p = strings;
6359
  curr_lst_sym = lst_syms;
6360
 
6361
  curr_bfd = abfd->archive_head;
6362
  while (curr_bfd != NULL)
6363
    {
6364
      unsigned int curr_count, i;
6365
      som_symbol_type *sym;
6366
 
6367
      /* Don't bother for non-SOM objects.  */
6368
      if (curr_bfd->format != bfd_object
6369
          || curr_bfd->xvec->flavour != bfd_target_som_flavour)
6370
        {
6371
          curr_bfd = curr_bfd->archive_next;
6372
          continue;
6373
        }
6374
 
6375
      /* Make sure the symbol table has been read, then snag a pointer
6376
         to it.  It's a little slimey to grab the symbols via obj_som_symtab,
6377
         but doing so avoids allocating lots of extra memory.  */
6378
      if (! som_slurp_symbol_table (curr_bfd))
6379
        goto error_return;
6380
 
6381
      sym = obj_som_symtab (curr_bfd);
6382
      curr_count = bfd_get_symcount (curr_bfd);
6383
 
6384
      for (i = 0; i < curr_count; i++, sym++)
6385
        {
6386
          struct som_misc_symbol_info info;
6387
          struct som_external_lst_symbol_record *last;
6388
          unsigned int symbol_pos;
6389
          unsigned int slen;
6390
          unsigned int symbol_key;
6391
          unsigned int flags;
6392
 
6393
          /* Derive SOM information from the BFD symbol.  */
6394
          som_bfd_derive_misc_symbol_info (curr_bfd, &sym->symbol, &info);
6395
 
6396
          /* Should we include this symbol?  */
6397
          if (info.symbol_type == ST_NULL
6398
              || info.symbol_type == ST_SYM_EXT
6399
              || info.symbol_type == ST_ARG_EXT)
6400
            continue;
6401
 
6402
          /* Only global symbols and unsatisfied commons.  */
6403
          if (info.symbol_scope != SS_UNIVERSAL
6404
              && info.symbol_type != ST_STORAGE)
6405
            continue;
6406
 
6407
          /* Do no include undefined symbols.  */
6408
          if (bfd_is_und_section (sym->symbol.section))
6409
            continue;
6410
 
6411
          /* If this is the first symbol from this SOM, then update
6412
             the SOM dictionary too.  */
6413
          if (bfd_getb32 (som_dict[som_index].location) == 0)
6414
            {
6415
              bfd_putb32 (curr_som_offset, som_dict[som_index].location);
6416
              bfd_putb32 (arelt_size (curr_bfd), som_dict[som_index].length);
6417
            }
6418
 
6419
          symbol_key = som_bfd_ar_symbol_hash (&sym->symbol);
6420
 
6421
          /* Fill in the lst symbol record.  */
6422
          flags = 0;
6423
          if (info.secondary_def)
6424
            flags |= LST_SYMBOL_SECONDARY_DEF;
6425
          flags |= info.symbol_type << LST_SYMBOL_SYMBOL_TYPE_SH;
6426
          flags |= info.symbol_scope << LST_SYMBOL_SYMBOL_SCOPE_SH;
6427
          if (bfd_is_com_section (sym->symbol.section))
6428
            flags |= LST_SYMBOL_IS_COMMON;
6429
          if (info.dup_common)
6430
            flags |= LST_SYMBOL_DUP_COMMON;
6431
          flags |= 3 << LST_SYMBOL_XLEAST_SH;
6432
          flags |= info.arg_reloc << LST_SYMBOL_ARG_RELOC_SH;
6433
          bfd_putb32 (flags, curr_lst_sym->flags);
6434
          bfd_putb32 (p - strings + 4, curr_lst_sym->name);
6435
          bfd_putb32 (0, curr_lst_sym->qualifier_name);
6436
          bfd_putb32 (info.symbol_info, curr_lst_sym->symbol_info);
6437
          bfd_putb32 (info.symbol_value | info.priv_level,
6438
                      curr_lst_sym->symbol_value);
6439
          bfd_putb32 (0, curr_lst_sym->symbol_descriptor);
6440
          curr_lst_sym->reserved = 0;
6441
          bfd_putb32 (som_index, curr_lst_sym->som_index);
6442
          bfd_putb32 (symbol_key, curr_lst_sym->symbol_key);
6443
          bfd_putb32 (0, curr_lst_sym->next_entry);
6444
 
6445
          /* Insert into the hash table.  */
6446
          symbol_pos =
6447
            (curr_lst_sym - lst_syms)
6448
            * sizeof (struct som_external_lst_symbol_record)
6449
            + hash_size * 4
6450
            + module_count * sizeof (struct som_external_som_entry)
6451
            + sizeof (struct som_external_lst_header);
6452
          last = last_hash_entry[symbol_key % hash_size];
6453
          if (last != NULL)
6454
            {
6455
              /* There is already something at the head of this hash chain,
6456
                 so tack this symbol onto the end of the chain.  */
6457
              bfd_putb32 (symbol_pos, last->next_entry);
6458
            }
6459
          else
6460
            /* First entry in this hash chain.  */
6461
            bfd_putb32 (symbol_pos, hash_table + 4 * (symbol_key % hash_size));
6462
 
6463
          /* Keep track of the last symbol we added to this chain so we can
6464
             easily update its next_entry pointer.  */
6465
          last_hash_entry[symbol_key % hash_size] = curr_lst_sym;
6466
 
6467
          /* Update the string table.  */
6468
          slen = strlen (sym->symbol.name);
6469
          bfd_put_32 (abfd, slen, p);
6470
          p += 4;
6471
          slen++; /* Nul terminator.  */
6472
          memcpy (p, sym->symbol.name, slen);
6473
          p += slen;
6474
          while (slen % 4)
6475
            {
6476
              bfd_put_8 (abfd, 0, p);
6477
              p++;
6478
              slen++;
6479
            }
6480
          BFD_ASSERT (p <= strings + string_size);
6481
 
6482
          /* Head to the next symbol.  */
6483
          curr_lst_sym++;
6484
        }
6485
 
6486
      /* Keep track of where each SOM will finally reside; then look
6487
         at the next BFD.  */
6488
      curr_som_offset += arelt_size (curr_bfd) + sizeof (struct ar_hdr);
6489
 
6490
      /* A particular object in the archive may have an odd length; the
6491
         linker requires objects begin on an even boundary.  So round
6492
         up the current offset as necessary.  */
6493
      curr_som_offset = (curr_som_offset + 0x1) &~ (unsigned) 1;
6494
      curr_bfd = curr_bfd->archive_next;
6495
      som_index++;
6496
    }
6497
 
6498
  /* Now scribble out the hash table.  */
6499
  amt = hash_size * 4;
6500
  if (bfd_bwrite ((void *) hash_table, amt, abfd) != amt)
6501
    goto error_return;
6502
 
6503
  /* Then the SOM dictionary.  */
6504
  amt = module_count * sizeof (struct som_external_som_entry);
6505
  if (bfd_bwrite ((void *) som_dict, amt, abfd) != amt)
6506
    goto error_return;
6507
 
6508
  /* The library symbols.  */
6509
  amt = nsyms * sizeof (struct som_external_lst_symbol_record);
6510
  if (bfd_bwrite ((void *) lst_syms, amt, abfd) != amt)
6511
    goto error_return;
6512
 
6513
  /* And finally the strings.  */
6514
  amt = string_size;
6515
  if (bfd_bwrite ((void *) strings, amt, abfd) != amt)
6516
    goto error_return;
6517
 
6518
  if (hash_table != NULL)
6519
    free (hash_table);
6520
  if (som_dict != NULL)
6521
    free (som_dict);
6522
  if (last_hash_entry != NULL)
6523
    free (last_hash_entry);
6524
  if (lst_syms != NULL)
6525
    free (lst_syms);
6526
  if (strings != NULL)
6527
    free (strings);
6528
  return TRUE;
6529
 
6530
 error_return:
6531
  if (hash_table != NULL)
6532
    free (hash_table);
6533
  if (som_dict != NULL)
6534
    free (som_dict);
6535
  if (last_hash_entry != NULL)
6536
    free (last_hash_entry);
6537
  if (lst_syms != NULL)
6538
    free (lst_syms);
6539
  if (strings != NULL)
6540
    free (strings);
6541
 
6542
  return FALSE;
6543
}
6544
 
6545
/* Write out the LST for the archive.
6546
 
6547
   You'll never believe this is really how armaps are handled in SOM...  */
6548
 
6549
static bfd_boolean
6550
som_write_armap (bfd *abfd,
6551
                 unsigned int elength,
6552
                 struct orl *map ATTRIBUTE_UNUSED,
6553
                 unsigned int orl_count ATTRIBUTE_UNUSED,
6554
                 int stridx ATTRIBUTE_UNUSED)
6555
{
6556
  bfd *curr_bfd;
6557
  struct stat statbuf;
6558
  unsigned int i, lst_size, nsyms, stringsize;
6559
  struct ar_hdr hdr;
6560
  struct som_external_lst_header lst;
6561
  unsigned char *p;
6562
  bfd_size_type amt;
6563
  unsigned int csum;
6564
  unsigned int module_count;
6565
 
6566
  /* We'll use this for the archive's date and mode later.  */
6567
  if (stat (abfd->filename, &statbuf) != 0)
6568
    {
6569
      bfd_set_error (bfd_error_system_call);
6570
      return FALSE;
6571
    }
6572
  /* Fudge factor.  */
6573
  bfd_ardata (abfd)->armap_timestamp = statbuf.st_mtime + 60;
6574
 
6575
  /* Account for the lst header first.  */
6576
  lst_size = sizeof (struct som_external_lst_header);
6577
 
6578
  /* Start building the LST header.  */
6579
  /* FIXME:  Do we need to examine each element to determine the
6580
     largest id number?  */
6581
  bfd_putb16 (CPU_PA_RISC1_0, &lst.system_id);
6582
  bfd_putb16 (LIBMAGIC, &lst.a_magic);
6583
  bfd_putb32 (VERSION_ID, &lst.version_id);
6584
  bfd_putb32 (0, &lst.file_time.secs);
6585
  bfd_putb32 (0, &lst.file_time.nanosecs);
6586
 
6587
  bfd_putb32 (lst_size, &lst.hash_loc);
6588
  bfd_putb32 (SOM_LST_HASH_SIZE, &lst.hash_size);
6589
 
6590
  /* Hash table is a SOM_LST_HASH_SIZE 32bit offsets.  */
6591
  lst_size += 4 * SOM_LST_HASH_SIZE;
6592
 
6593
  /* We need to count the number of SOMs in this archive.  */
6594
  curr_bfd = abfd->archive_head;
6595
  module_count = 0;
6596
  while (curr_bfd != NULL)
6597
    {
6598
      /* Only true SOM objects count.  */
6599
      if (curr_bfd->format == bfd_object
6600
          && curr_bfd->xvec->flavour == bfd_target_som_flavour)
6601
        module_count++;
6602
      curr_bfd = curr_bfd->archive_next;
6603
    }
6604
  bfd_putb32 (module_count, &lst.module_count);
6605
  bfd_putb32 (module_count, &lst.module_limit);
6606
  bfd_putb32 (lst_size, &lst.dir_loc);
6607
  lst_size += sizeof (struct som_external_som_entry) * module_count;
6608
 
6609
  /* We don't support import/export tables, auxiliary headers,
6610
     or free lists yet.  Make the linker work a little harder
6611
     to make our life easier.  */
6612
 
6613
  bfd_putb32 (0, &lst.export_loc);
6614
  bfd_putb32 (0, &lst.export_count);
6615
  bfd_putb32 (0, &lst.import_loc);
6616
  bfd_putb32 (0, &lst.aux_loc);
6617
  bfd_putb32 (0, &lst.aux_size);
6618
 
6619
  /* Count how many symbols we will have on the hash chains and the
6620
     size of the associated string table.  */
6621
  if (! som_bfd_prep_for_ar_write (abfd, &nsyms, &stringsize))
6622
    return FALSE;
6623
 
6624
  lst_size += sizeof (struct som_external_lst_symbol_record) * nsyms;
6625
 
6626
  /* For the string table.  One day we might actually use this info
6627
     to avoid small seeks/reads when reading archives.  */
6628
  bfd_putb32 (lst_size, &lst.string_loc);
6629
  bfd_putb32 (stringsize, &lst.string_size);
6630
  lst_size += stringsize;
6631
 
6632
  /* SOM ABI says this must be zero.  */
6633
  bfd_putb32 (0, &lst.free_list);
6634
  bfd_putb32 (lst_size, &lst.file_end);
6635
 
6636
  /* Compute the checksum.  Must happen after the entire lst header
6637
     has filled in.  */
6638
  p = (unsigned char *) &lst;
6639
  csum = 0;
6640
  for (i = 0; i < sizeof (struct som_external_lst_header) - sizeof (int);
6641
       i += 4)
6642
    csum ^= bfd_getb32 (&p[i]);
6643
  bfd_putb32 (csum, &lst.checksum);
6644
 
6645
  sprintf (hdr.ar_name, "/              ");
6646
  _bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%-12ld",
6647
                    bfd_ardata (abfd)->armap_timestamp);
6648
  _bfd_ar_spacepad (hdr.ar_uid, sizeof (hdr.ar_uid), "%ld",
6649
                    statbuf.st_uid);
6650
  _bfd_ar_spacepad (hdr.ar_gid, sizeof (hdr.ar_gid), "%ld",
6651
                    statbuf.st_gid);
6652
  _bfd_ar_spacepad (hdr.ar_mode, sizeof (hdr.ar_mode), "%-8o",
6653
                    (unsigned int)statbuf.st_mode);
6654
  _bfd_ar_spacepad (hdr.ar_size, sizeof (hdr.ar_size), "%-10d",
6655
                    (int) lst_size);
6656
  hdr.ar_fmag[0] = '`';
6657
  hdr.ar_fmag[1] = '\012';
6658
 
6659
  /* Turn any nulls into spaces.  */
6660
  for (i = 0; i < sizeof (struct ar_hdr); i++)
6661
    if (((char *) (&hdr))[i] == '\0')
6662
      (((char *) (&hdr))[i]) = ' ';
6663
 
6664
  /* Scribble out the ar header.  */
6665
  amt = sizeof (struct ar_hdr);
6666
  if (bfd_bwrite ((void *) &hdr, amt, abfd) != amt)
6667
    return FALSE;
6668
 
6669
  /* Now scribble out the lst header.  */
6670
  amt = sizeof (struct som_external_lst_header);
6671
  if (bfd_bwrite ((void *) &lst, amt, abfd) != amt)
6672
    return FALSE;
6673
 
6674
  /* Build and write the armap.  */
6675
  if (!som_bfd_ar_write_symbol_stuff (abfd, nsyms, stringsize, lst, elength))
6676
    return FALSE;
6677
 
6678
  /* Done.  */
6679
  return TRUE;
6680
}
6681
 
6682
/* Free all information we have cached for this BFD.  We can always
6683
   read it again later if we need it.  */
6684
 
6685
static bfd_boolean
6686
som_bfd_free_cached_info (bfd *abfd)
6687
{
6688
  asection *o;
6689
 
6690
  if (bfd_get_format (abfd) != bfd_object)
6691
    return TRUE;
6692
 
6693
#define FREE(x) if (x != NULL) { free (x); x = NULL; }
6694
  /* Free the native string and symbol tables.  */
6695
  FREE (obj_som_symtab (abfd));
6696
  FREE (obj_som_stringtab (abfd));
6697
  for (o = abfd->sections; o != NULL; o = o->next)
6698
    {
6699
      /* Free the native relocations.  */
6700
      o->reloc_count = (unsigned) -1;
6701
      FREE (som_section_data (o)->reloc_stream);
6702
      /* Do not free the generic relocations as they are objalloc'ed.  */
6703
    }
6704
#undef FREE
6705
 
6706
  return TRUE;
6707
}
6708
 
6709
/* End of miscellaneous support functions.  */
6710
 
6711
/* Linker support functions.  */
6712
 
6713
static bfd_boolean
6714
som_bfd_link_split_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
6715
{
6716
  return som_is_subspace (sec) && sec->size > 240000;
6717
}
6718
 
6719
#define som_close_and_cleanup                   som_bfd_free_cached_info
6720
#define som_read_ar_hdr                         _bfd_generic_read_ar_hdr
6721
#define som_write_ar_hdr                        _bfd_generic_write_ar_hdr
6722
#define som_openr_next_archived_file            bfd_generic_openr_next_archived_file
6723
#define som_get_elt_at_index                    _bfd_generic_get_elt_at_index
6724
#define som_generic_stat_arch_elt               bfd_generic_stat_arch_elt
6725
#define som_truncate_arname                     bfd_bsd_truncate_arname
6726
#define som_slurp_extended_name_table           _bfd_slurp_extended_name_table
6727
#define som_construct_extended_name_table       _bfd_archive_coff_construct_extended_name_table
6728
#define som_update_armap_timestamp              bfd_true
6729
#define som_bfd_is_target_special_symbol   ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
6730
#define som_get_lineno                          _bfd_nosymbols_get_lineno
6731
#define som_bfd_make_debug_symbol               _bfd_nosymbols_bfd_make_debug_symbol
6732
#define som_read_minisymbols                    _bfd_generic_read_minisymbols
6733
#define som_minisymbol_to_symbol                _bfd_generic_minisymbol_to_symbol
6734
#define som_get_section_contents_in_window      _bfd_generic_get_section_contents_in_window
6735
#define som_bfd_get_relocated_section_contents  bfd_generic_get_relocated_section_contents
6736
#define som_bfd_relax_section                   bfd_generic_relax_section
6737
#define som_bfd_link_hash_table_create          _bfd_generic_link_hash_table_create
6738
#define som_bfd_link_hash_table_free            _bfd_generic_link_hash_table_free
6739
#define som_bfd_link_add_symbols                _bfd_generic_link_add_symbols
6740
#define som_bfd_link_just_syms                  _bfd_generic_link_just_syms
6741
#define som_bfd_copy_link_hash_symbol_type \
6742
  _bfd_generic_copy_link_hash_symbol_type
6743
#define som_bfd_final_link                      _bfd_generic_final_link
6744
#define som_bfd_gc_sections                     bfd_generic_gc_sections
6745
#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
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
6773
  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
6774
  bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* Data.  */
6775
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
6776
  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
6777
  bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* Headers.  */
6778
  {_bfd_dummy_target,
6779
   som_object_p,                /* bfd_check_format.  */
6780
   bfd_generic_archive_p,
6781
   _bfd_dummy_target
6782
  },
6783
  {
6784
    bfd_false,
6785
    som_mkobject,
6786
    _bfd_generic_mkarchive,
6787
    bfd_false
6788
  },
6789
  {
6790
    bfd_false,
6791
    som_write_object_contents,
6792
    _bfd_write_archive_contents,
6793
    bfd_false,
6794
  },
6795
#undef som
6796
 
6797
  BFD_JUMP_TABLE_GENERIC (som),
6798
  BFD_JUMP_TABLE_COPY (som),
6799
  BFD_JUMP_TABLE_CORE (_bfd_nocore),
6800
  BFD_JUMP_TABLE_ARCHIVE (som),
6801
  BFD_JUMP_TABLE_SYMBOLS (som),
6802
  BFD_JUMP_TABLE_RELOCS (som),
6803
  BFD_JUMP_TABLE_WRITE (som),
6804
  BFD_JUMP_TABLE_LINK (som),
6805
  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
6806
 
6807
  NULL,
6808
 
6809
  NULL
6810
};
6811
 

powered by: WebSVN 2.1.0

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