Coverage Report

Created: 2023-06-29 07:13

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