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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-6.8/] [bfd/] [som.c] - Blame information for rev 816

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

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

powered by: WebSVN 2.1.0

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