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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [bfd/] [som.c] - Blame information for rev 831

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

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