Coverage Report

Created: 2026-09-14 08:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/binutils-gdb/bfd/som.c
Line
Count
Source
1
/* bfd back-end for HP PA-RISC SOM objects.
2
   Copyright (C) 1990-2026 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
132k
#define CPU_PA_RISC1_0 0x20B
47
#endif /* CPU_PA_RISC1_0 */
48
49
#ifndef CPU_PA_RISC1_1
50
264k
#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
132k
#define _PA_RISC1_0_ID CPU_PA_RISC1_0
59
#endif /* _PA_RISC1_0_ID */
60
61
#ifndef _PA_RISC1_1_ID
62
132k
#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
118k
#define _PA_RISC_MAXID  0x2FF
71
#endif /* _PA_RISC_MAXID */
72
73
#ifndef _PA_RISC_ID
74
#define _PA_RISC_ID(__m_num)    \
75
132k
    (((__m_num) == _PA_RISC1_0_ID) ||  \
76
132k
     ((__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
138
#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
1.67k
#define SOM_TMP_BUFSIZE 8192
98
99
/* Size of the hash table in archives.  */
100
8
#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
507
  (((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
1.16k
{
908
1.16k
  queue[0].reloc = NULL;
909
1.16k
  queue[0].size = 0;
910
1.16k
  queue[1].reloc = NULL;
911
1.16k
  queue[1].size = 0;
912
1.16k
  queue[2].reloc = NULL;
913
1.16k
  queue[2].size = 0;
914
1.16k
  queue[3].reloc = NULL;
915
1.16k
  queue[3].size = 0;
916
1.16k
}
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
16.6k
{
925
16.6k
  queue[3].reloc = queue[2].reloc;
926
16.6k
  queue[3].size = queue[2].size;
927
16.6k
  queue[2].reloc = queue[1].reloc;
928
16.6k
  queue[2].size = queue[1].size;
929
16.6k
  queue[1].reloc = queue[0].reloc;
930
16.6k
  queue[1].size = queue[0].size;
931
16.6k
  queue[0].reloc = p;
932
16.6k
  queue[0].size = size;
933
16.6k
}
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
10.9k
{
941
10.9k
  if (idx == 0)
942
4.21k
    return;
943
944
6.70k
  if (idx == 1)
945
3.96k
    {
946
3.96k
      unsigned char *tmp1 = queue[0].reloc;
947
3.96k
      unsigned int tmp2 = queue[0].size;
948
949
3.96k
      queue[0].reloc = queue[1].reloc;
950
3.96k
      queue[0].size = queue[1].size;
951
3.96k
      queue[1].reloc = tmp1;
952
3.96k
      queue[1].size = tmp2;
953
3.96k
      return;
954
3.96k
    }
955
956
2.74k
  if (idx == 2)
957
860
    {
958
860
      unsigned char *tmp1 = queue[0].reloc;
959
860
      unsigned int tmp2 = queue[0].size;
960
961
860
      queue[0].reloc = queue[2].reloc;
962
860
      queue[0].size = queue[2].size;
963
860
      queue[2].reloc = queue[1].reloc;
964
860
      queue[2].size = queue[1].size;
965
860
      queue[1].reloc = tmp1;
966
860
      queue[1].size = tmp2;
967
860
      return;
968
860
    }
969
970
1.88k
  if (idx == 3)
971
1.88k
    {
972
1.88k
      unsigned char *tmp1 = queue[0].reloc;
973
1.88k
      unsigned int tmp2 = queue[0].size;
974
975
1.88k
      queue[0].reloc = queue[3].reloc;
976
1.88k
      queue[0].size = queue[3].size;
977
1.88k
      queue[3].reloc = queue[2].reloc;
978
1.88k
      queue[3].size = queue[2].size;
979
1.88k
      queue[2].reloc = queue[1].reloc;
980
1.88k
      queue[2].size = queue[1].size;
981
1.88k
      queue[1].reloc = tmp1;
982
1.88k
      queue[1].size = tmp2;
983
1.88k
      return;
984
1.88k
    }
985
1.88k
  abort ();
986
1.88k
}
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
378
{
995
378
  if (queue[0].reloc && !memcmp (p, queue[0].reloc, size)
996
125
      && size == queue[0].size)
997
125
    return 0;
998
253
  if (queue[1].reloc && !memcmp (p, queue[1].reloc, size)
999
15
      && size == queue[1].size)
1000
15
    return 1;
1001
238
  if (queue[2].reloc && !memcmp (p, queue[2].reloc, size)
1002
19
      && size == queue[2].size)
1003
19
    return 2;
1004
219
  if (queue[3].reloc && !memcmp (p, queue[3].reloc, size)
1005
11
      && size == queue[3].size)
1006
11
    return 3;
1007
208
  return -1;
1008
219
}
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
378
{
1017
378
  int queue_index = som_reloc_queue_find (p, size, queue);
1018
1019
378
  if (queue_index != -1)
1020
170
    {
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
170
      bfd_put_8 (abfd, R_PREV_FIXUP + queue_index, p);
1025
170
      p += 1;
1026
170
      *subspace_reloc_sizep += 1;
1027
170
      som_reloc_queue_fix (queue, queue_index);
1028
170
    }
1029
208
  else
1030
208
    {
1031
208
      som_reloc_queue_insert (p, size, queue);
1032
208
      *subspace_reloc_sizep += size;
1033
208
      p += size;
1034
208
    }
1035
378
  return p;
1036
378
}
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
1.21k
{
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
1.21k
  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
1.21k
  if ((skip & 3) == 0 && skip <= 0xc0000 && skip > 0)
1074
252
    {
1075
      /* Difference can be handled in a simple single-byte
1076
   R_NO_RELOCATION entry.  */
1077
252
      if (skip <= 0x60)
1078
229
  {
1079
229
    bfd_put_8 (abfd, R_NO_RELOCATION + (skip >> 2) - 1, p);
1080
229
    *subspace_reloc_sizep += 1;
1081
229
    p++;
1082
229
  }
1083
      /* Handle it with a two byte R_NO_RELOCATION entry.  */
1084
23
      else if (skip <= 0x1000)
1085
23
  {
1086
23
    bfd_put_8 (abfd, R_NO_RELOCATION + 24 + (((skip >> 2) - 1) >> 8), p);
1087
23
    bfd_put_8 (abfd, (skip >> 2) - 1, p + 1);
1088
23
    p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 2, queue);
1089
23
  }
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
252
    }
1098
  /* Ugh.  Punt and use a 4 byte entry.  */
1099
958
  else if (skip > 0)
1100
17
    {
1101
17
      bfd_put_8 (abfd, R_NO_RELOCATION + 31, p);
1102
17
      bfd_put_8 (abfd, (skip - 1) >> 16, p + 1);
1103
17
      bfd_put_16 (abfd, (bfd_vma) skip - 1, p + 2);
1104
17
      p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 4, queue);
1105
17
    }
1106
1.21k
  return p;
1107
1.21k
}
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
40
{
1121
40
  if (addend + 0x80 < 0x100)
1122
1
    {
1123
1
      bfd_put_8 (abfd, R_DATA_OVERRIDE + 1, p);
1124
1
      bfd_put_8 (abfd, addend, p + 1);
1125
1
      p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 2, queue);
1126
1
    }
1127
39
  else if (addend + 0x8000 < 0x10000)
1128
19
    {
1129
19
      bfd_put_8 (abfd, R_DATA_OVERRIDE + 2, p);
1130
19
      bfd_put_16 (abfd, addend, p + 1);
1131
19
      p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 3, queue);
1132
19
    }
1133
20
  else if (addend + 0x800000 < 0x1000000)
1134
2
    {
1135
2
      bfd_put_8 (abfd, R_DATA_OVERRIDE + 3, p);
1136
2
      bfd_put_8 (abfd, addend >> 16, p + 1);
1137
2
      bfd_put_16 (abfd, addend, p + 2);
1138
2
      p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 4, queue);
1139
2
    }
1140
18
  else
1141
18
    {
1142
18
      bfd_put_8 (abfd, R_DATA_OVERRIDE + 4, p);
1143
18
      bfd_put_32 (abfd, addend, p + 1);
1144
18
      p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 5, queue);
1145
18
    }
1146
40
  return p;
1147
40
}
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
169
{
1159
169
  int arg_bits = HPPA_R_ARG_RELOC (bfd_reloc->addend);
1160
169
  int rtn_bits = arg_bits & 0x3;
1161
169
  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
169
  if (sym_num < 0x100)
1175
169
    {
1176
169
      switch (arg_bits)
1177
169
  {
1178
22
  case 0:
1179
32
  case 1:
1180
32
    type = 0;
1181
32
    break;
1182
6
  case 1 << 8:
1183
16
  case 1 << 8 | 1:
1184
16
    type = 1;
1185
16
    break;
1186
4
  case 1 << 8 | 1 << 6:
1187
6
  case 1 << 8 | 1 << 6 | 1:
1188
6
    type = 2;
1189
6
    break;
1190
6
  case 1 << 8 | 1 << 6 | 1 << 4:
1191
15
  case 1 << 8 | 1 << 6 | 1 << 4 | 1:
1192
15
    type = 3;
1193
15
    break;
1194
4
  case 1 << 8 | 1 << 6 | 1 << 4 | 1 << 2:
1195
57
  case 1 << 8 | 1 << 6 | 1 << 4 | 1 << 2 | 1:
1196
57
    type = 4;
1197
57
    break;
1198
43
  default:
1199
    /* Not one of the easy encodings.  This will have to be
1200
       handled by the more complex code below.  */
1201
43
    type = -1;
1202
43
    break;
1203
169
  }
1204
169
      if (type != -1)
1205
126
  {
1206
    /* Account for the return value too.  */
1207
126
    if (rtn_bits)
1208
84
      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
126
    bfd_put_8 (abfd, bfd_reloc->howto->type + type, p);
1213
126
    bfd_put_8 (abfd, sym_num, p + 1);
1214
126
    p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 2, queue);
1215
126
    done = 1;
1216
126
  }
1217
169
    }
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
169
  if (! done)
1223
43
    {
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
43
      type = rtn_bits;
1227
43
      if ((arg_bits >> 6 & 0xf) == 0xe)
1228
8
  type += 9 * 40;
1229
35
      else
1230
35
  type += (3 * (arg_bits >> 8 & 3) + (arg_bits >> 6 & 3)) * 40;
1231
43
      if ((arg_bits >> 2 & 0xf) == 0xe)
1232
8
  type += 9 * 4;
1233
35
      else
1234
35
  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
43
      bfd_put_8 (abfd, bfd_reloc->howto->type + 10
1239
43
     + 2 * (sym_num >= 0x100) + (type >= 0x100),
1240
43
     p);
1241
43
      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
43
      if (sym_num < 0x100)
1246
43
  {
1247
43
    bfd_put_8 (abfd, sym_num, p + 2);
1248
43
    p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 3, queue);
1249
43
  }
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
43
    }
1257
169
  return p;
1258
169
}
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
36.6k
{
1266
36.6k
  int log = 0;
1267
1268
  /* Test for 0 or a power of 2.  */
1269
36.6k
  if (x == 0 || x != (x & -x))
1270
345
    return -1;
1271
1272
526k
  while ((x >>= 1) != 0)
1273
490k
    log++;
1274
36.3k
  return log;
1275
36.6k
}
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
2.25k
{
1286
2.25k
  if (output_bfd)
1287
0
    reloc_entry->address += input_section->output_offset;
1288
1289
2.25k
  return bfd_reloc_ok;
1290
2.25k
}
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
137k
{
1606
137k
  dst->secs = bfd_getb32 (src->secs);
1607
137k
  dst->nanosecs = bfd_getb32 (src->nanosecs);
1608
137k
}
1609
1610
static void
1611
som_swap_clock_out (struct som_clock *src,
1612
        struct som_external_clock *dst)
1613
127
{
1614
127
  bfd_putb32 (src->secs, dst->secs);
1615
127
  bfd_putb32 (src->nanosecs, dst->nanosecs);
1616
127
}
1617
1618
static void
1619
som_swap_header_in (struct som_external_header *src,
1620
        struct som_header *dst)
1621
132k
{
1622
132k
  dst->system_id = bfd_getb16 (src->system_id);
1623
132k
  dst->a_magic = bfd_getb16 (src->a_magic);
1624
132k
  dst->version_id = bfd_getb32 (src->version_id);
1625
132k
  som_swap_clock_in (&src->file_time, &dst->file_time);
1626
132k
  dst->entry_space = bfd_getb32 (src->entry_space);
1627
132k
  dst->entry_subspace = bfd_getb32 (src->entry_subspace);
1628
132k
  dst->entry_offset = bfd_getb32 (src->entry_offset);
1629
132k
  dst->aux_header_location = bfd_getb32 (src->aux_header_location);
1630
132k
  dst->aux_header_size = bfd_getb32 (src->aux_header_size);
1631
132k
  dst->som_length = bfd_getb32 (src->som_length);
1632
132k
  dst->presumed_dp = bfd_getb32 (src->presumed_dp);
1633
132k
  dst->space_location = bfd_getb32 (src->space_location);
1634
132k
  dst->space_total = bfd_getb32 (src->space_total);
1635
132k
  dst->subspace_location = bfd_getb32 (src->subspace_location);
1636
132k
  dst->subspace_total = bfd_getb32 (src->subspace_total);
1637
132k
  dst->loader_fixup_location = bfd_getb32 (src->loader_fixup_location);
1638
132k
  dst->loader_fixup_total = bfd_getb32 (src->loader_fixup_total);
1639
132k
  dst->space_strings_location = bfd_getb32 (src->space_strings_location);
1640
132k
  dst->space_strings_size = bfd_getb32 (src->space_strings_size);
1641
132k
  dst->init_array_location = bfd_getb32 (src->init_array_location);
1642
132k
  dst->init_array_total = bfd_getb32 (src->init_array_total);
1643
132k
  dst->compiler_location = bfd_getb32 (src->compiler_location);
1644
132k
  dst->compiler_total = bfd_getb32 (src->compiler_total);
1645
132k
  dst->symbol_location = bfd_getb32 (src->symbol_location);
1646
132k
  dst->symbol_total = bfd_getb32 (src->symbol_total);
1647
132k
  dst->fixup_request_location = bfd_getb32 (src->fixup_request_location);
1648
132k
  dst->fixup_request_total = bfd_getb32 (src->fixup_request_total);
1649
132k
  dst->symbol_strings_location = bfd_getb32 (src->symbol_strings_location);
1650
132k
  dst->symbol_strings_size = bfd_getb32 (src->symbol_strings_size);
1651
132k
  dst->unloadable_sp_location = bfd_getb32 (src->unloadable_sp_location);
1652
132k
  dst->unloadable_sp_size = bfd_getb32 (src->unloadable_sp_size);
1653
132k
  dst->checksum = bfd_getb32 (src->checksum);
1654
132k
}
1655
1656
static void
1657
som_swap_header_out (struct som_header *src,
1658
        struct som_external_header *dst)
1659
127
{
1660
127
  bfd_putb16 (src->system_id, dst->system_id);
1661
127
  bfd_putb16 (src->a_magic, dst->a_magic);
1662
127
  bfd_putb32 (src->version_id, dst->version_id);
1663
127
  som_swap_clock_out (&src->file_time, &dst->file_time);
1664
127
  bfd_putb32 (src->entry_space, dst->entry_space);
1665
127
  bfd_putb32 (src->entry_subspace, dst->entry_subspace);
1666
127
  bfd_putb32 (src->entry_offset, dst->entry_offset);
1667
127
  bfd_putb32 (src->aux_header_location, dst->aux_header_location);
1668
127
  bfd_putb32 (src->aux_header_size, dst->aux_header_size);
1669
127
  bfd_putb32 (src->som_length, dst->som_length);
1670
127
  bfd_putb32 (src->presumed_dp, dst->presumed_dp);
1671
127
  bfd_putb32 (src->space_location, dst->space_location);
1672
127
  bfd_putb32 (src->space_total, dst->space_total);
1673
127
  bfd_putb32 (src->subspace_location, dst->subspace_location);
1674
127
  bfd_putb32 (src->subspace_total, dst->subspace_total);
1675
127
  bfd_putb32 (src->loader_fixup_location, dst->loader_fixup_location);
1676
127
  bfd_putb32 (src->loader_fixup_total, dst->loader_fixup_total);
1677
127
  bfd_putb32 (src->space_strings_location, dst->space_strings_location);
1678
127
  bfd_putb32 (src->space_strings_size, dst->space_strings_size);
1679
127
  bfd_putb32 (src->init_array_location, dst->init_array_location);
1680
127
  bfd_putb32 (src->init_array_total, dst->init_array_total);
1681
127
  bfd_putb32 (src->compiler_location, dst->compiler_location);
1682
127
  bfd_putb32 (src->compiler_total, dst->compiler_total);
1683
127
  bfd_putb32 (src->symbol_location, dst->symbol_location);
1684
127
  bfd_putb32 (src->symbol_total, dst->symbol_total);
1685
127
  bfd_putb32 (src->fixup_request_location, dst->fixup_request_location);
1686
127
  bfd_putb32 (src->fixup_request_total, dst->fixup_request_total);
1687
127
  bfd_putb32 (src->symbol_strings_location, dst->symbol_strings_location);
1688
127
  bfd_putb32 (src->symbol_strings_size, dst->symbol_strings_size);
1689
127
  bfd_putb32 (src->unloadable_sp_location, dst->unloadable_sp_location);
1690
127
  bfd_putb32 (src->unloadable_sp_size, dst->unloadable_sp_size);
1691
127
  bfd_putb32 (src->checksum, dst->checksum);
1692
127
}
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
13.5k
{
1698
13.5k
  unsigned int flags;
1699
1700
13.5k
  dst->name = bfd_getb32 (src->name);
1701
13.5k
  flags = bfd_getb32 (src->flags);
1702
13.5k
  dst->is_loadable = (flags & SOM_SPACE_IS_LOADABLE) != 0;
1703
13.5k
  dst->is_defined = (flags & SOM_SPACE_IS_DEFINED) != 0;
1704
13.5k
  dst->is_private = (flags & SOM_SPACE_IS_PRIVATE) != 0;
1705
13.5k
  dst->has_intermediate_code = (flags & SOM_SPACE_HAS_INTERMEDIATE_CODE) != 0;
1706
13.5k
  dst->is_tspecific = (flags & SOM_SPACE_IS_TSPECIFIC) != 0;
1707
13.5k
  dst->reserved = 0;
1708
13.5k
  dst->sort_key = (flags >> SOM_SPACE_SORT_KEY_SH) & SOM_SPACE_SORT_KEY_MASK;
1709
13.5k
  dst->reserved2 = 0;
1710
13.5k
  dst->space_number = bfd_getb32 (src->space_number);
1711
13.5k
  dst->subspace_index = bfd_getb32 (src->subspace_index);
1712
13.5k
  dst->subspace_quantity = bfd_getb32 (src->subspace_quantity);
1713
13.5k
  dst->loader_fix_index = bfd_getb32 (src->loader_fix_index);
1714
13.5k
  dst->loader_fix_quantity = bfd_getb32 (src->loader_fix_quantity);
1715
13.5k
  dst->init_pointer_index = bfd_getb32 (src->init_pointer_index);
1716
13.5k
  dst->init_pointer_quantity = bfd_getb32 (src->init_pointer_quantity);
1717
13.5k
}
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
88
{
1723
88
  unsigned int flags;
1724
1725
88
  bfd_putb32 (src->name, dst->name);
1726
1727
88
  flags = 0;
1728
88
  if (src->is_loadable)
1729
3
    flags |= SOM_SPACE_IS_LOADABLE;
1730
88
  if (src->is_defined)
1731
31
    flags |= SOM_SPACE_IS_DEFINED;
1732
88
  if (src->is_private)
1733
41
    flags |= SOM_SPACE_IS_PRIVATE;
1734
88
  if (src->has_intermediate_code)
1735
0
    flags |= SOM_SPACE_HAS_INTERMEDIATE_CODE;
1736
88
  if (src->is_tspecific)
1737
0
    flags |= SOM_SPACE_IS_TSPECIFIC;
1738
88
  flags |= (src->sort_key & SOM_SPACE_SORT_KEY_MASK) << SOM_SPACE_SORT_KEY_SH;
1739
88
  bfd_putb32 (flags, dst->flags);
1740
88
  bfd_putb32 (src->space_number, dst->space_number);
1741
88
  bfd_putb32 (src->subspace_index, dst->subspace_index);
1742
88
  bfd_putb32 (src->subspace_quantity, dst->subspace_quantity);
1743
88
  bfd_putb32 (src->loader_fix_index, dst->loader_fix_index);
1744
88
  bfd_putb32 (src->loader_fix_quantity, dst->loader_fix_quantity);
1745
88
  bfd_putb32 (src->init_pointer_index, dst->init_pointer_index);
1746
88
  bfd_putb32 (src->init_pointer_quantity, dst->init_pointer_quantity);
1747
88
}
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
36.8k
{
1754
36.8k
  unsigned int flags;
1755
36.8k
  dst->space_index = bfd_getb32 (src->space_index);
1756
36.8k
  flags = bfd_getb32 (src->flags);
1757
36.8k
  dst->access_control_bits = (flags >> SOM_SUBSPACE_ACCESS_CONTROL_BITS_SH)
1758
36.8k
    & SOM_SUBSPACE_ACCESS_CONTROL_BITS_MASK;
1759
36.8k
  dst->memory_resident = (flags & SOM_SUBSPACE_MEMORY_RESIDENT) != 0;
1760
36.8k
  dst->dup_common = (flags & SOM_SUBSPACE_DUP_COMMON) != 0;
1761
36.8k
  dst->is_common = (flags & SOM_SUBSPACE_IS_COMMON) != 0;
1762
36.8k
  dst->is_loadable = (flags & SOM_SUBSPACE_IS_LOADABLE) != 0;
1763
36.8k
  dst->quadrant = (flags >> SOM_SUBSPACE_QUADRANT_SH)
1764
36.8k
    & SOM_SUBSPACE_QUADRANT_MASK;
1765
36.8k
  dst->initially_frozen = (flags & SOM_SUBSPACE_INITIALLY_FROZEN) != 0;
1766
36.8k
  dst->is_first = (flags & SOM_SUBSPACE_IS_FIRST) != 0;
1767
36.8k
  dst->code_only = (flags & SOM_SUBSPACE_CODE_ONLY) != 0;
1768
36.8k
  dst->sort_key = (flags >> SOM_SUBSPACE_SORT_KEY_SH)
1769
36.8k
    & SOM_SUBSPACE_SORT_KEY_MASK;
1770
36.8k
  dst->replicate_init = (flags & SOM_SUBSPACE_REPLICATE_INIT) != 0;
1771
36.8k
  dst->continuation = (flags & SOM_SUBSPACE_CONTINUATION) != 0;
1772
36.8k
  dst->is_tspecific = (flags & SOM_SUBSPACE_IS_TSPECIFIC) != 0;
1773
36.8k
  dst->is_comdat = (flags & SOM_SUBSPACE_IS_COMDAT) != 0;
1774
36.8k
  dst->reserved = 0;
1775
36.8k
  dst->file_loc_init_value = bfd_getb32 (src->file_loc_init_value);
1776
36.8k
  dst->initialization_length = bfd_getb32 (src->initialization_length);
1777
36.8k
  dst->subspace_start = bfd_getb32 (src->subspace_start);
1778
36.8k
  dst->subspace_length = bfd_getb32 (src->subspace_length);
1779
36.8k
  dst->alignment = bfd_getb32 (src->alignment);
1780
36.8k
  dst->name = bfd_getb32 (src->name);
1781
36.8k
  dst->fixup_request_index = bfd_getb32 (src->fixup_request_index);
1782
36.8k
  dst->fixup_request_quantity = bfd_getb32 (src->fixup_request_quantity);
1783
36.8k
}
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
21
{
1790
21
  unsigned int flags;
1791
1792
21
  bfd_putb32 (src->space_index, dst->space_index);
1793
21
  flags = (src->access_control_bits & SOM_SUBSPACE_ACCESS_CONTROL_BITS_MASK)
1794
21
    << SOM_SUBSPACE_ACCESS_CONTROL_BITS_SH;
1795
21
  if (src->memory_resident)
1796
0
    flags |= SOM_SUBSPACE_MEMORY_RESIDENT;
1797
21
  if (src->dup_common)
1798
4
    flags |= SOM_SUBSPACE_DUP_COMMON;
1799
21
  if (src->is_common)
1800
4
    flags |= SOM_SUBSPACE_IS_COMMON;
1801
21
  if (src->is_loadable)
1802
3
    flags |= SOM_SUBSPACE_IS_LOADABLE;
1803
21
  flags |= (src->quadrant & SOM_SUBSPACE_QUADRANT_MASK)
1804
21
    << SOM_SUBSPACE_QUADRANT_SH;
1805
21
  if (src->initially_frozen)
1806
0
    flags |= SOM_SUBSPACE_INITIALLY_FROZEN;
1807
21
  if (src->is_first)
1808
0
    flags |= SOM_SUBSPACE_IS_FIRST;
1809
21
  if (src->code_only)
1810
10
    flags |= SOM_SUBSPACE_CODE_ONLY;
1811
21
  flags |= (src->sort_key & SOM_SUBSPACE_SORT_KEY_MASK)
1812
21
    << SOM_SUBSPACE_SORT_KEY_SH;
1813
21
  if (src->replicate_init)
1814
0
    flags |= SOM_SUBSPACE_REPLICATE_INIT;
1815
21
  if (src->continuation)
1816
0
    flags |= SOM_SUBSPACE_CONTINUATION;
1817
21
  if (src->is_tspecific)
1818
0
    flags |= SOM_SUBSPACE_IS_TSPECIFIC;
1819
21
  if (src->is_comdat)
1820
3
    flags |= SOM_SUBSPACE_IS_COMDAT;
1821
21
  bfd_putb32 (flags, dst->flags);
1822
21
  bfd_putb32 (src->file_loc_init_value, dst->file_loc_init_value);
1823
21
  bfd_putb32 (src->initialization_length, dst->initialization_length);
1824
21
  bfd_putb32 (src->subspace_start, dst->subspace_start);
1825
21
  bfd_putb32 (src->subspace_length, dst->subspace_length);
1826
21
  bfd_putb32 (src->alignment, dst->alignment);
1827
21
  bfd_putb32 (src->name, dst->name);
1828
21
  bfd_putb32 (src->fixup_request_index, dst->fixup_request_index);
1829
21
  bfd_putb32 (src->fixup_request_quantity, dst->fixup_request_quantity);
1830
21
}
1831
1832
static void
1833
som_swap_aux_id_in (struct som_external_aux_id *src,
1834
        struct som_aux_id *dst)
1835
1.56k
{
1836
1.56k
  unsigned int flags = bfd_getb32 (src->flags);
1837
1838
1.56k
  dst->mandatory = (flags & SOM_AUX_ID_MANDATORY) != 0;
1839
1.56k
  dst->copy = (flags & SOM_AUX_ID_COPY) != 0;
1840
1.56k
  dst->append = (flags & SOM_AUX_ID_APPEND) != 0;
1841
1.56k
  dst->ignore = (flags & SOM_AUX_ID_IGNORE) != 0;
1842
1.56k
  dst->type = (flags >> SOM_AUX_ID_TYPE_SH) & SOM_AUX_ID_TYPE_MASK;
1843
1.56k
  dst->length = bfd_getb32 (src->length);
1844
1.56k
}
1845
1846
static void
1847
som_swap_aux_id_out (struct som_aux_id *src,
1848
        struct som_external_aux_id *dst)
1849
112
{
1850
112
  unsigned int flags = 0;
1851
1852
112
  if (src->mandatory)
1853
0
    flags |= SOM_AUX_ID_MANDATORY;
1854
112
  if (src->copy)
1855
0
    flags |= SOM_AUX_ID_COPY;
1856
112
  if (src->append)
1857
0
    flags |= SOM_AUX_ID_APPEND;
1858
112
  if (src->ignore)
1859
0
    flags |= SOM_AUX_ID_IGNORE;
1860
112
  flags |= (src->type & SOM_AUX_ID_TYPE_MASK) << SOM_AUX_ID_TYPE_SH;
1861
112
  bfd_putb32 (flags, dst->flags);
1862
112
  bfd_putb32 (src->length, dst->length);
1863
112
}
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
1.56k
{
1890
1.56k
  som_swap_aux_id_in (&src->som_auxhdr, &dst->som_auxhdr);
1891
1.56k
  dst->exec_tsize = bfd_getb32 (src->exec_tsize);
1892
1.56k
  dst->exec_tmem = bfd_getb32 (src->exec_tmem);
1893
1.56k
  dst->exec_tfile = bfd_getb32 (src->exec_tfile);
1894
1.56k
  dst->exec_dsize = bfd_getb32 (src->exec_dsize);
1895
1.56k
  dst->exec_dmem = bfd_getb32 (src->exec_dmem);
1896
1.56k
  dst->exec_dfile = bfd_getb32 (src->exec_dfile);
1897
1.56k
  dst->exec_bsize = bfd_getb32 (src->exec_bsize);
1898
1.56k
  dst->exec_entry = bfd_getb32 (src->exec_entry);
1899
1.56k
  dst->exec_flags = bfd_getb32 (src->exec_flags);
1900
1.56k
  dst->exec_bfill = bfd_getb32 (src->exec_bfill);
1901
1.56k
}
1902
1903
static void
1904
som_swap_exec_auxhdr_out (struct som_exec_auxhdr *src,
1905
       struct som_external_exec_auxhdr *dst)
1906
112
{
1907
112
  som_swap_aux_id_out (&src->som_auxhdr, &dst->som_auxhdr);
1908
112
  bfd_putb32 (src->exec_tsize, dst->exec_tsize);
1909
112
  bfd_putb32 (src->exec_tmem, dst->exec_tmem);
1910
112
  bfd_putb32 (src->exec_tfile, dst->exec_tfile);
1911
112
  bfd_putb32 (src->exec_dsize, dst->exec_dsize);
1912
112
  bfd_putb32 (src->exec_dmem, dst->exec_dmem);
1913
112
  bfd_putb32 (src->exec_dfile, dst->exec_dfile);
1914
112
  bfd_putb32 (src->exec_bsize, dst->exec_bsize);
1915
112
  bfd_putb32 (src->exec_entry, dst->exec_entry);
1916
112
  bfd_putb32 (src->exec_flags, dst->exec_flags);
1917
112
  bfd_putb32 (src->exec_bfill, dst->exec_bfill);
1918
112
}
1919
1920
static void
1921
som_swap_lst_header_in (struct som_external_lst_header *src,
1922
      struct som_lst_header *dst)
1923
5.40k
{
1924
5.40k
  dst->system_id = bfd_getb16 (src->system_id);
1925
5.40k
  dst->a_magic = bfd_getb16 (src->a_magic);
1926
5.40k
  dst->version_id = bfd_getb32 (src->version_id);
1927
5.40k
  som_swap_clock_in (&src->file_time, &dst->file_time);
1928
5.40k
  dst->hash_loc = bfd_getb32 (src->hash_loc);
1929
5.40k
  dst->hash_size = bfd_getb32 (src->hash_size);
1930
5.40k
  dst->module_count = bfd_getb32 (src->module_count);
1931
5.40k
  dst->module_limit = bfd_getb32 (src->module_limit);
1932
5.40k
  dst->dir_loc = bfd_getb32 (src->dir_loc);
1933
5.40k
  dst->export_loc = bfd_getb32 (src->export_loc);
1934
5.40k
  dst->export_count = bfd_getb32 (src->export_count);
1935
5.40k
  dst->import_loc = bfd_getb32 (src->import_loc);
1936
5.40k
  dst->aux_loc = bfd_getb32 (src->aux_loc);
1937
5.40k
  dst->aux_size = bfd_getb32 (src->aux_size);
1938
5.40k
  dst->string_loc = bfd_getb32 (src->string_loc);
1939
5.40k
  dst->string_size = bfd_getb32 (src->string_size);
1940
5.40k
  dst->free_list = bfd_getb32 (src->free_list);
1941
5.40k
  dst->file_end = bfd_getb32 (src->file_end);
1942
5.40k
  dst->checksum = bfd_getb32 (src->checksum);
1943
5.40k
}
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
1.47k
{
1954
1.47k
  asection *section;
1955
1956
  /* som_mkobject will set bfd_error if som_mkobject fails.  */
1957
1.47k
  if (! som_mkobject (abfd))
1958
0
    return NULL;
1959
1960
  /* Set BFD flags based on what information is available in the SOM.  */
1961
1.47k
  abfd->flags = BFD_NO_FLAGS;
1962
1.47k
  if (file_hdrp->symbol_total)
1963
1.19k
    abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
1964
1965
1.47k
  switch (file_hdrp->a_magic)
1966
1.47k
    {
1967
11
    case DEMAND_MAGIC:
1968
11
      abfd->flags |= (D_PAGED | WP_TEXT | EXEC_P);
1969
11
      break;
1970
336
    case SHARE_MAGIC:
1971
336
      abfd->flags |= (WP_TEXT | EXEC_P);
1972
336
      break;
1973
619
    case EXEC_MAGIC:
1974
619
      abfd->flags |= (EXEC_P);
1975
619
      break;
1976
342
    case RELOC_MAGIC:
1977
342
      abfd->flags |= HAS_RELOC;
1978
342
      break;
1979
0
#ifdef SHL_MAGIC
1980
93
    case SHL_MAGIC:
1981
93
#endif
1982
93
#ifdef DL_MAGIC
1983
163
    case DL_MAGIC:
1984
163
#endif
1985
163
      abfd->flags |= DYNAMIC;
1986
163
      break;
1987
1988
8
    default:
1989
8
      break;
1990
1.47k
    }
1991
1992
  /* Save the auxiliary header.  */
1993
1.47k
  obj_som_exec_hdr (abfd) = aux_hdrp;
1994
1995
  /* Allocate space to hold the saved exec header information.  */
1996
1.47k
  obj_som_exec_data (abfd) = bfd_zalloc (abfd, (bfd_size_type) sizeof (struct som_exec_data));
1997
1.47k
  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
1.47k
  if (aux_hdrp)
2016
1.03k
    {
2017
1.03k
      int found = 0;
2018
2019
15.1k
      for (section = abfd->sections; section; section = section->next)
2020
14.0k
  {
2021
14.0k
    bfd_vma entry;
2022
2023
14.0k
    if ((section->flags & SEC_CODE) == 0)
2024
10.0k
      continue;
2025
4.06k
    entry = aux_hdrp->exec_entry + aux_hdrp->exec_tmem;
2026
4.06k
    if (entry >= section->vma
2027
2.98k
        && entry < section->vma + section->size)
2028
1.89k
      found = 1;
2029
4.06k
  }
2030
1.03k
      if ((aux_hdrp->exec_entry == 0 && !(abfd->flags & DYNAMIC))
2031
756
    || (aux_hdrp->exec_entry & 0x3) != 0
2032
466
    || ! found)
2033
1.00k
  {
2034
1.00k
    abfd->start_address = aux_hdrp->exec_flags;
2035
1.00k
    obj_som_exec_data (abfd)->exec_flags = aux_hdrp->exec_entry;
2036
1.00k
  }
2037
28
      else
2038
28
  {
2039
28
    abfd->start_address = aux_hdrp->exec_entry + current_offset;
2040
28
    obj_som_exec_data (abfd)->exec_flags = aux_hdrp->exec_flags;
2041
28
  }
2042
1.03k
    }
2043
2044
1.47k
  obj_som_exec_data (abfd)->version_id = file_hdrp->version_id;
2045
2046
1.47k
  bfd_default_set_arch_mach (abfd, bfd_arch_hppa, pa10);
2047
1.47k
  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
1.47k
  obj_som_stringtab (abfd) = NULL;
2053
1.47k
  obj_som_symtab (abfd) = NULL;
2054
1.47k
  obj_som_sorted_syms (abfd) = NULL;
2055
1.47k
  obj_som_stringtab_size (abfd) = file_hdrp->symbol_strings_size;
2056
1.47k
  obj_som_sym_filepos (abfd) = file_hdrp->symbol_location + current_offset;
2057
1.47k
  obj_som_str_filepos (abfd) = (file_hdrp->symbol_strings_location
2058
1.47k
        + current_offset);
2059
1.47k
  obj_som_reloc_filepos (abfd) = (file_hdrp->fixup_request_location
2060
1.47k
          + current_offset);
2061
1.47k
  obj_som_exec_data (abfd)->system_id = file_hdrp->system_id;
2062
2063
1.47k
  return _bfd_no_cleanup;
2064
1.47k
}
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
2.66k
{
2077
2.66k
  char *space_strings = NULL;
2078
2.66k
  unsigned int space_index, i;
2079
2.66k
  unsigned int total_subspaces = 0;
2080
2.66k
  asection **subspace_sections = NULL;
2081
2.66k
  asection *section;
2082
2.66k
  size_t amt;
2083
2084
  /* First, read in space names.  */
2085
2.66k
  amt = file_hdr->space_strings_size;
2086
2.66k
  if (amt == (size_t) -1)
2087
0
    {
2088
0
      bfd_set_error (bfd_error_no_memory);
2089
0
      goto error_return;
2090
0
    }
2091
2.66k
  if (bfd_seek (abfd, current_offset + file_hdr->space_strings_location,
2092
2.66k
    SEEK_SET) != 0)
2093
0
    goto error_return;
2094
2.66k
  space_strings = (char *) _bfd_malloc_and_read (abfd, amt + 1, amt);
2095
2.66k
  if (space_strings == NULL)
2096
66
    goto error_return;
2097
  /* Make sure that the string table is NUL terminated.  */
2098
2.59k
  space_strings[amt] = 0;
2099
2100
  /* Loop over all of the space dictionaries, building up sections.  */
2101
15.2k
  for (space_index = 0; space_index < file_hdr->space_total; space_index++)
2102
13.7k
    {
2103
13.7k
      struct som_space_dictionary_record space;
2104
13.7k
      struct som_external_space_dictionary_record ext_space;
2105
13.7k
      char *space_name;
2106
13.7k
      struct som_external_subspace_dictionary_record ext_subspace;
2107
13.7k
      struct som_subspace_dictionary_record subspace, save_subspace;
2108
13.7k
      unsigned int subspace_index;
2109
13.7k
      asection *space_asect;
2110
13.7k
      bfd_size_type space_size = 0;
2111
13.7k
      char *newname;
2112
2113
      /* Read the space dictionary element.  */
2114
13.7k
      if (bfd_seek (abfd,
2115
13.7k
        (current_offset + file_hdr->space_location
2116
13.7k
         + space_index * sizeof (ext_space)),
2117
13.7k
        SEEK_SET) != 0)
2118
0
  goto error_return;
2119
13.7k
      amt = sizeof ext_space;
2120
13.7k
      if (bfd_read (&ext_space, amt, abfd) != amt)
2121
222
  goto error_return;
2122
2123
13.5k
      som_swap_space_dictionary_in (&ext_space, &space);
2124
2125
      /* Setup the space name string.  */
2126
13.5k
      if (space.name >= file_hdr->space_strings_size)
2127
113
  goto error_return;
2128
2129
13.4k
      space_name = space.name + space_strings;
2130
2131
      /* Make a section out of it.  */
2132
13.4k
      amt = strlen (space_name) + 1;
2133
13.4k
      newname = bfd_alloc (abfd, amt);
2134
13.4k
      if (!newname)
2135
0
  goto error_return;
2136
13.4k
      strcpy (newname, space_name);
2137
2138
13.4k
      space_asect = bfd_make_section_anyway (abfd, newname);
2139
13.4k
      if (!space_asect)
2140
0
  goto error_return;
2141
2142
13.4k
      if (space.is_loadable == 0)
2143
11.1k
  space_asect->flags |= SEC_DEBUGGING;
2144
2145
      /* Set up all the attributes for the space.  */
2146
13.4k
      if (! bfd_som_set_section_attributes (space_asect, space.is_defined,
2147
13.4k
              space.is_private, space.sort_key,
2148
13.4k
              space.space_number))
2149
0
  goto error_return;
2150
2151
      /* If the space has no subspaces, then we're done.  */
2152
13.4k
      if (space.subspace_quantity == 0)
2153
5.05k
  continue;
2154
2155
      /* Now, read in the first subspace for this space.  */
2156
8.34k
      if (bfd_seek (abfd,
2157
8.34k
        (current_offset + file_hdr->subspace_location
2158
8.34k
         + space.subspace_index * sizeof ext_subspace),
2159
8.34k
        SEEK_SET) != 0)
2160
24
  goto error_return;
2161
8.32k
      amt = sizeof ext_subspace;
2162
8.32k
      if (bfd_read (&ext_subspace, amt, abfd) != amt)
2163
80
  goto error_return;
2164
      /* Seek back to the start of the subspaces for loop below.  */
2165
8.24k
      if (bfd_seek (abfd,
2166
8.24k
        (current_offset + file_hdr->subspace_location
2167
8.24k
         + space.subspace_index * sizeof ext_subspace),
2168
8.24k
        SEEK_SET) != 0)
2169
0
  goto error_return;
2170
2171
8.24k
      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.24k
      space_asect->vma = subspace.subspace_start;
2176
8.24k
      space_asect->filepos = subspace.file_loc_init_value + current_offset;
2177
8.24k
      space_asect->alignment_power = exact_log2 (subspace.alignment);
2178
8.24k
      if (space_asect->alignment_power == (unsigned) -1)
2179
83
  goto error_return;
2180
2181
      /* Initialize save_subspace so we can reliably determine if this
2182
   loop placed any useful values into it.  */
2183
8.16k
      memset (&save_subspace, 0, sizeof (save_subspace));
2184
2185
      /* Loop over the rest of the subspaces, building up more sections.  */
2186
36.3k
      for (subspace_index = 0; subspace_index < space.subspace_quantity;
2187
28.1k
     subspace_index++)
2188
28.7k
  {
2189
28.7k
    asection *subspace_asect;
2190
28.7k
    char *subspace_name;
2191
2192
    /* Read in the next subspace.  */
2193
28.7k
    amt = sizeof ext_subspace;
2194
28.7k
    if (bfd_read (&ext_subspace, amt, abfd) != amt)
2195
105
      goto error_return;
2196
2197
28.6k
    som_swap_subspace_dictionary_in (&ext_subspace, &subspace);
2198
2199
    /* Setup the subspace name string.  */
2200
28.6k
    if (subspace.name >= file_hdr->space_strings_size)
2201
228
      goto error_return;
2202
2203
28.4k
    subspace_name = subspace.name + space_strings;
2204
2205
28.4k
    amt = strlen (subspace_name) + 1;
2206
28.4k
    newname = bfd_alloc (abfd, amt);
2207
28.4k
    if (!newname)
2208
0
      goto error_return;
2209
28.4k
    strcpy (newname, subspace_name);
2210
2211
    /* Make a section out of this subspace.  */
2212
28.4k
    subspace_asect = bfd_make_section_anyway (abfd, newname);
2213
28.4k
    if (!subspace_asect)
2214
0
      goto error_return;
2215
2216
    /* Store private information about the section.  */
2217
28.4k
    if (! bfd_som_set_subsection_attributes (subspace_asect, space_asect,
2218
28.4k
               subspace.access_control_bits,
2219
28.4k
               subspace.sort_key,
2220
28.4k
               subspace.quadrant,
2221
28.4k
               subspace.is_comdat,
2222
28.4k
               subspace.is_common,
2223
28.4k
               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
28.4k
    total_subspaces++;
2236
28.4k
    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
28.4k
    switch (subspace.access_control_bits >> 4)
2241
28.4k
      {
2242
      /* Readonly data.  */
2243
19.9k
      case 0x0:
2244
19.9k
        subspace_asect->flags |= SEC_DATA | SEC_READONLY;
2245
19.9k
        break;
2246
2247
      /* Normal data.  */
2248
2.06k
      case 0x1:
2249
2.06k
        subspace_asect->flags |= SEC_DATA;
2250
2.06k
        break;
2251
2252
      /* Readonly code and the gateways.
2253
         Gateways have other attributes which do not map
2254
         into anything BFD knows about.  */
2255
674
      case 0x2:
2256
1.49k
      case 0x4:
2257
1.63k
      case 0x5:
2258
2.49k
      case 0x6:
2259
5.00k
      case 0x7:
2260
5.00k
        subspace_asect->flags |= SEC_CODE | SEC_READONLY;
2261
5.00k
        break;
2262
2263
      /* dynamic (writable) code.  */
2264
1.42k
      case 0x3:
2265
1.42k
        subspace_asect->flags |= SEC_CODE;
2266
1.42k
        break;
2267
28.4k
      }
2268
2269
28.4k
    if (subspace.is_comdat || subspace.is_common || subspace.dup_common)
2270
16.3k
      subspace_asect->flags |= SEC_LINK_ONCE;
2271
2272
28.4k
    if (subspace.subspace_length > 0)
2273
19.5k
      subspace_asect->flags |= SEC_HAS_CONTENTS;
2274
2275
28.4k
    if (subspace.is_loadable)
2276
7.34k
      subspace_asect->flags |= SEC_ALLOC | SEC_LOAD;
2277
21.0k
    else
2278
21.0k
      subspace_asect->flags |= SEC_DEBUGGING;
2279
2280
28.4k
    if (subspace.code_only)
2281
8.44k
      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
28.4k
    if (subspace.file_loc_init_value == 0
2286
10.4k
        && subspace.initialization_length == 0)
2287
845
      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
28.4k
    if (subspace.fixup_request_quantity != 0)
2294
22.8k
      {
2295
22.8k
        subspace_asect->flags |= SEC_RELOC;
2296
22.8k
        subspace_asect->rel_filepos = subspace.fixup_request_index;
2297
22.8k
        som_section_data (subspace_asect)->reloc_size
2298
22.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
22.8k
        subspace_asect->reloc_count = (unsigned) -1;
2302
22.8k
      }
2303
2304
    /* Update save_subspace if appropriate.  */
2305
28.4k
    if (subspace.file_loc_init_value > save_subspace.file_loc_init_value)
2306
9.89k
      save_subspace = subspace;
2307
2308
28.4k
    subspace_asect->vma = subspace.subspace_start;
2309
28.4k
    subspace_asect->size = subspace.subspace_length;
2310
28.4k
    subspace_asect->filepos = (subspace.file_loc_init_value
2311
28.4k
             + current_offset);
2312
28.4k
    subspace_asect->alignment_power = exact_log2 (subspace.alignment);
2313
28.4k
    if (subspace_asect->alignment_power == (unsigned) -1)
2314
262
      goto error_return;
2315
2316
    /* Keep track of the accumulated sizes of the sections.  */
2317
28.1k
    space_size += subspace.subspace_length;
2318
28.1k
  }
2319
2320
      /* This can happen for a .o which defines symbols in otherwise
2321
   empty subspaces.  */
2322
7.56k
      if (!save_subspace.file_loc_init_value)
2323
1.20k
  space_asect->size = 0;
2324
6.35k
      else
2325
6.35k
  {
2326
6.35k
    if (file_hdr->a_magic != RELOC_MAGIC)
2327
2.72k
      {
2328
        /* Setup the size for the space section based upon the info
2329
     in the last subspace of the space.  */
2330
2.72k
        space_asect->size = (save_subspace.subspace_start
2331
2.72k
           - space_asect->vma
2332
2.72k
           + save_subspace.subspace_length);
2333
2.72k
      }
2334
3.62k
    else
2335
3.62k
      {
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
3.62k
        space_asect->size = space_size;
2342
3.62k
      }
2343
6.35k
  }
2344
7.56k
    }
2345
  /* Now that we've read in all the subspace records, we need to assign
2346
     a target index to each subspace.  */
2347
1.47k
  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
1.47k
  subspace_sections = bfd_malloc (amt);
2353
1.47k
  if (subspace_sections == NULL)
2354
0
    goto error_return;
2355
2356
16.6k
  for (i = 0, section = abfd->sections; section; section = section->next)
2357
15.1k
    {
2358
15.1k
      if (!som_is_subspace (section))
2359
5.12k
  continue;
2360
2361
10.0k
      subspace_sections[i] = section;
2362
10.0k
      i++;
2363
10.0k
    }
2364
1.47k
  qsort (subspace_sections, total_subspaces,
2365
1.47k
   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
11.5k
  for (i = 0; i < total_subspaces; i++)
2370
10.0k
    subspace_sections[i]->target_index = i;
2371
2372
1.47k
  free (space_strings);
2373
1.47k
  free (subspace_sections);
2374
1.47k
  return true;
2375
2376
1.18k
 error_return:
2377
1.18k
  free (space_strings);
2378
1.18k
  free (subspace_sections);
2379
1.18k
  return false;
2380
1.47k
}
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
184k
{
2388
184k
  struct som_external_header ext_file_hdr;
2389
184k
  struct som_header file_hdr;
2390
184k
  struct som_exec_auxhdr *aux_hdr_ptr = NULL;
2391
184k
  unsigned long current_offset = 0;
2392
184k
  struct som_external_lst_header ext_lst_header;
2393
184k
  struct som_external_som_entry ext_som_entry;
2394
184k
  size_t amt;
2395
184k
  unsigned int loc;
2396
184k
#define ENTRY_SIZE sizeof (struct som_external_som_entry)
2397
2398
184k
  amt = sizeof (struct som_external_header);
2399
184k
  if (bfd_read (&ext_file_hdr, amt, abfd) != amt)
2400
52.1k
    {
2401
52.1k
      if (bfd_get_error () != bfd_error_system_call)
2402
51.9k
  bfd_set_error (bfd_error_wrong_format);
2403
52.1k
      return NULL;
2404
52.1k
    }
2405
2406
132k
  som_swap_header_in (&ext_file_hdr, &file_hdr);
2407
2408
132k
  if (!_PA_RISC_ID (file_hdr.system_id))
2409
129k
    {
2410
129k
      bfd_set_error (bfd_error_wrong_format);
2411
129k
      return NULL;
2412
129k
    }
2413
2414
3.00k
  switch (file_hdr.a_magic)
2415
3.00k
    {
2416
721
    case RELOC_MAGIC:
2417
1.59k
    case EXEC_MAGIC:
2418
2.09k
    case SHARE_MAGIC:
2419
2.12k
    case DEMAND_MAGIC:
2420
2.46k
    case DL_MAGIC:
2421
2.88k
    case SHL_MAGIC:
2422
#ifdef SHARED_MAGIC_CNX
2423
    case SHARED_MAGIC_CNX:
2424
#endif
2425
2.88k
      break;
2426
2427
43
    case EXECLIBMAGIC:
2428
      /* Read the lst header and determine where the SOM directory begins.  */
2429
2430
43
      if (bfd_seek (abfd, 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
43
      amt = sizeof (struct som_external_lst_header);
2438
43
      if (bfd_read (&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
43
      loc = bfd_getb32 (ext_lst_header.dir_loc);
2447
43
      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
43
      amt = ENTRY_SIZE;
2455
43
      if (bfd_read (&ext_som_entry, amt, abfd) != amt)
2456
11
  {
2457
11
    if (bfd_get_error () != bfd_error_system_call)
2458
11
      bfd_set_error (bfd_error_wrong_format);
2459
11
    return NULL;
2460
11
  }
2461
2462
      /* Now position to the first SOM.  */
2463
32
      current_offset = bfd_getb32 (ext_som_entry.location);
2464
32
      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
32
      amt = sizeof (struct som_external_header);
2473
32
      if (bfd_read (&ext_file_hdr, amt, abfd) != amt)
2474
12
  {
2475
12
    if (bfd_get_error () != bfd_error_system_call)
2476
12
      bfd_set_error (bfd_error_wrong_format);
2477
12
    return NULL;
2478
12
  }
2479
2480
20
      som_swap_header_in (&ext_file_hdr, &file_hdr);
2481
2482
20
      break;
2483
2484
71
    default:
2485
71
      bfd_set_error (bfd_error_wrong_format);
2486
71
      return NULL;
2487
3.00k
    }
2488
2489
2.90k
  if (file_hdr.version_id != OLD_VERSION_ID
2490
783
      && file_hdr.version_id != NEW_VERSION_ID)
2491
146
    {
2492
146
      bfd_set_error (bfd_error_wrong_format);
2493
146
      return NULL;
2494
146
    }
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
2.76k
  if (file_hdr.aux_header_size != 0)
2500
1.66k
    {
2501
1.66k
      struct som_external_exec_auxhdr ext_exec_auxhdr;
2502
2503
1.66k
      aux_hdr_ptr = bfd_zalloc (abfd,
2504
1.66k
        (bfd_size_type) sizeof (*aux_hdr_ptr));
2505
1.66k
      if (aux_hdr_ptr == NULL)
2506
0
  return NULL;
2507
1.66k
      amt = sizeof (struct som_external_exec_auxhdr);
2508
1.66k
      if (bfd_read (&ext_exec_auxhdr, amt, abfd) != amt)
2509
99
  {
2510
99
    if (bfd_get_error () != bfd_error_system_call)
2511
99
      bfd_set_error (bfd_error_wrong_format);
2512
99
    return NULL;
2513
99
  }
2514
1.56k
      som_swap_exec_auxhdr_in (&ext_exec_auxhdr, aux_hdr_ptr);
2515
1.56k
    }
2516
2517
2.66k
  if (!setup_sections (abfd, &file_hdr, current_offset))
2518
1.18k
    {
2519
      /* setup_sections does not bubble up a bfd error code.  */
2520
1.18k
      bfd_set_error (bfd_error_bad_value);
2521
1.18k
      return NULL;
2522
1.18k
    }
2523
2524
  /* This appears to be a valid SOM object.  Do some initialization.  */
2525
1.47k
  return som_object_setup (abfd, &file_hdr, aux_hdr_ptr, current_offset);
2526
2.66k
}
2527
2528
/* Create a SOM object.  */
2529
2530
static bool
2531
som_mkobject (bfd *abfd)
2532
1.74k
{
2533
  /* Allocate memory to hold backend information.  */
2534
1.74k
  abfd->tdata.som_data = bfd_zalloc (abfd, (bfd_size_type) sizeof (struct som_data_struct));
2535
1.74k
  if (abfd->tdata.som_data == NULL)
2536
0
    return false;
2537
1.74k
  return true;
2538
1.74k
}
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
161
{
2547
161
  struct som_header *file_hdr;
2548
161
  asection *section;
2549
161
  size_t amt = sizeof (struct som_header);
2550
2551
  /* Make and attach a file header to the BFD.  */
2552
161
  file_hdr = bfd_zalloc (abfd, amt);
2553
161
  if (file_hdr == NULL)
2554
0
    return false;
2555
161
  obj_som_file_hdr (abfd) = file_hdr;
2556
2557
161
  if (abfd->flags & (EXEC_P | DYNAMIC))
2558
138
    {
2559
      /* Make and attach an exec header to the BFD.  */
2560
138
      amt = sizeof (struct som_exec_auxhdr);
2561
138
      obj_som_exec_hdr (abfd) = bfd_zalloc (abfd, amt);
2562
138
      if (obj_som_exec_hdr (abfd) == NULL)
2563
0
  return false;
2564
2565
138
      if (abfd->flags & D_PAGED)
2566
138
  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
138
    }
2576
23
  else
2577
23
    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
161
  file_hdr->file_time.secs = 0;
2583
161
  file_hdr->file_time.nanosecs = 0;
2584
2585
161
  file_hdr->entry_space = 0;
2586
161
  file_hdr->entry_subspace = 0;
2587
161
  file_hdr->entry_offset = 0;
2588
161
  file_hdr->presumed_dp = 0;
2589
2590
  /* Now iterate over the sections translating information from
2591
     BFD sections to SOM spaces/subspaces.  */
2592
368
  for (section = abfd->sections; section != NULL; section = section->next)
2593
207
    {
2594
      /* Ignore anything which has not been marked as a space or
2595
   subspace.  */
2596
207
      if (!som_is_space (section) && !som_is_subspace (section))
2597
0
  continue;
2598
2599
207
      if (som_is_space (section))
2600
137
  {
2601
    /* Allocate space for the space dictionary.  */
2602
137
    amt = sizeof (struct som_space_dictionary_record);
2603
137
    som_section_data (section)->space_dict = bfd_zalloc (abfd, amt);
2604
137
    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
137
    som_section_data (section)->space_dict->loader_fix_index = -1;
2609
137
    som_section_data (section)->space_dict->init_pointer_index = -1;
2610
2611
    /* Set more attributes that were stuffed away in private data.  */
2612
137
    som_section_data (section)->space_dict->sort_key =
2613
137
      som_section_data (section)->copy_data->sort_key;
2614
137
    som_section_data (section)->space_dict->is_defined =
2615
137
      som_section_data (section)->copy_data->is_defined;
2616
137
    som_section_data (section)->space_dict->is_private =
2617
137
      som_section_data (section)->copy_data->is_private;
2618
137
    som_section_data (section)->space_dict->space_number =
2619
137
      som_section_data (section)->copy_data->space_number;
2620
137
  }
2621
70
      else
2622
70
  {
2623
    /* Allocate space for the subspace dictionary.  */
2624
70
    amt = sizeof (struct som_subspace_dictionary_record);
2625
70
    som_section_data (section)->subspace_dict = bfd_zalloc (abfd, amt);
2626
70
    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
70
    if (section->flags & SEC_ALLOC)
2633
18
      som_section_data (section)->subspace_dict->is_loadable = 1;
2634
2635
70
    if (section->flags & SEC_CODE)
2636
22
      som_section_data (section)->subspace_dict->code_only = 1;
2637
2638
70
    som_section_data (section)->subspace_dict->subspace_start =
2639
70
      section->vma;
2640
70
    som_section_data (section)->subspace_dict->subspace_length =
2641
70
      section->size;
2642
70
    som_section_data (section)->subspace_dict->initialization_length =
2643
70
      section->size;
2644
70
    som_section_data (section)->subspace_dict->alignment =
2645
70
      1 << section->alignment_power;
2646
2647
    /* Set more attributes that were stuffed away in private data.  */
2648
70
    som_section_data (section)->subspace_dict->sort_key =
2649
70
      som_section_data (section)->copy_data->sort_key;
2650
70
    som_section_data (section)->subspace_dict->access_control_bits =
2651
70
      som_section_data (section)->copy_data->access_control_bits;
2652
70
    som_section_data (section)->subspace_dict->quadrant =
2653
70
      som_section_data (section)->copy_data->quadrant;
2654
70
    som_section_data (section)->subspace_dict->is_comdat =
2655
70
      som_section_data (section)->copy_data->is_comdat;
2656
70
    som_section_data (section)->subspace_dict->is_common =
2657
70
      som_section_data (section)->copy_data->is_common;
2658
70
    som_section_data (section)->subspace_dict->dup_common =
2659
70
      som_section_data (section)->copy_data->dup_common;
2660
70
  }
2661
207
    }
2662
161
  return true;
2663
161
}
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
2.07k
{
2670
  /* If no copy data is available, then it's neither a space nor a
2671
     subspace.  */
2672
2.07k
  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
2.07k
  if (som_section_data (section)->copy_data->container != section
2678
576
      && (som_section_data (section)->copy_data->container->output_section
2679
576
    != section))
2680
576
    return false;
2681
2682
  /* OK.  Must be a space.  */
2683
1.49k
  return true;
2684
2.07k
}
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
17.9k
{
2691
  /* If no copy data is available, then it's neither a space nor a
2692
     subspace.  */
2693
17.9k
  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
17.9k
  if (som_section_data (section)->copy_data->container == section
2699
11.0k
      || (som_section_data (section)->copy_data->container->output_section
2700
11.0k
    == section))
2701
6.91k
    return false;
2702
2703
  /* OK.  Must be a subspace.  */
2704
11.0k
  return true;
2705
17.9k
}
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
487
{
2714
487
  return (som_section_data (subspace)->copy_data->container == space)
2715
235
    || (som_section_data (subspace)->copy_data->container->output_section
2716
235
  == space);
2717
487
}
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
322
{
2724
322
  int count = 0;
2725
322
  asection *section;
2726
2727
736
  for (section = abfd->sections; section != NULL; section = section->next)
2728
414
    count += som_is_space (section);
2729
2730
322
  return count;
2731
322
}
2732
2733
/* Count the number of subspaces attached to the given BFD.  */
2734
2735
static unsigned long
2736
som_count_subspaces (bfd *abfd)
2737
161
{
2738
161
  int count = 0;
2739
161
  asection *section;
2740
2741
368
  for (section = abfd->sections; section != NULL; section = section->next)
2742
207
    count += som_is_subspace (section);
2743
2744
161
  return count;
2745
161
}
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
353
{
2756
353
  asymbol **sym1 = (asymbol **) arg1;
2757
353
  asymbol **sym2 = (asymbol **) arg2;
2758
353
  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
353
  if ((*sym1)->flags & BSF_SECTION_SYM)
2763
0
    count1 = (*sym1)->udata.i;
2764
353
  else
2765
353
    count1 = som_symbol_data (*sym1)->reloc_count;
2766
2767
353
  if ((*sym2)->flags & BSF_SECTION_SYM)
2768
0
    count2 = (*sym2)->udata.i;
2769
353
  else
2770
353
    count2 = som_symbol_data (*sym2)->reloc_count;
2771
2772
  /* Return the appropriate value.  */
2773
353
  if (count1 < count2)
2774
2
    return 1;
2775
351
  else if (count1 > count2)
2776
30
    return -1;
2777
321
  return 0;
2778
353
}
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
41.1k
{
2786
41.1k
  asection **subspace1 = (asection **) arg1;
2787
41.1k
  asection **subspace2 = (asection **) arg2;
2788
2789
41.1k
  if ((*subspace1)->target_index < (*subspace2)->target_index)
2790
6.36k
    return -1;
2791
34.7k
  else if ((*subspace2)->target_index < (*subspace1)->target_index)
2792
16.6k
    return 1;
2793
18.0k
  else
2794
18.0k
    return 0;
2795
41.1k
}
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
161
{
2802
161
  unsigned long i;
2803
161
  asection *section;
2804
161
  asymbol **sorted_syms;
2805
161
  size_t amt;
2806
2807
161
  if (num_syms == 0)
2808
119
    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
288
  for (i = 0; i < num_syms; i++)
2816
246
    {
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
246
      if (som_symbol_data (syms[i]) == NULL
2821
246
    || 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
246
      else
2827
246
  som_symbol_data (syms[i])->reloc_count = 0;
2828
246
    }
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
154
  for (section = abfd->sections; section != NULL; section = section->next)
2833
112
    {
2834
112
      int j;
2835
2836
      /* Does this section have any relocations?  */
2837
112
      if ((int) section->reloc_count <= 0)
2838
86
  continue;
2839
2840
      /* Walk through each relocation for this section.  */
2841
830
      for (j = 1; j < (int) section->reloc_count; j++)
2842
804
  {
2843
804
    arelent *reloc = section->orelocation[j];
2844
804
    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
804
    if (reloc->sym_ptr_ptr == NULL
2850
804
        || bfd_is_abs_section ((*reloc->sym_ptr_ptr)->section))
2851
737
      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
67
    if (reloc->howto->type == R_DP_RELATIVE
2858
56
        || reloc->howto->type == R_CODE_ONE_SYMBOL)
2859
33
      scale = 2;
2860
34
    else
2861
34
      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
67
    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
67
    som_symbol_data (*reloc->sym_ptr_ptr)->reloc_count += scale;
2875
67
  }
2876
26
    }
2877
2878
  /* Sort a copy of the symbol table, rather than the canonical
2879
     output symbol table.  */
2880
42
  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
42
  sorted_syms = bfd_zalloc (abfd, amt);
2886
42
  if (sorted_syms == NULL)
2887
0
    return false;
2888
42
  memcpy (sorted_syms, syms, num_syms * sizeof (asymbol *));
2889
42
  qsort (sorted_syms, num_syms, sizeof (asymbol *), compare_syms);
2890
42
  obj_som_sorted_syms (abfd) = sorted_syms;
2891
2892
  /* Compute the symbol indexes, they will be needed by the relocation
2893
     code.  */
2894
288
  for (i = 0; i < num_syms; i++)
2895
246
    {
2896
      /* A section symbol.  Again, there is no pointer to backend symbol
2897
   information, so we reuse the udata field again.  */
2898
246
      if (sorted_syms[i]->flags & BSF_SECTION_SYM)
2899
0
  sorted_syms[i]->udata.i = i;
2900
246
      else
2901
246
  som_symbol_data (sorted_syms[i])->index = i;
2902
246
    }
2903
42
  return true;
2904
42
}
2905
2906
static bool
2907
som_write_fixups (bfd *abfd,
2908
      unsigned long current_offset,
2909
      unsigned int *total_reloc_sizep)
2910
161
{
2911
161
  unsigned int i, j;
2912
  /* Chunk of memory that we can use as buffer space, then throw
2913
     away.  */
2914
161
  unsigned char tmp_space[SOM_TMP_BUFSIZE];
2915
161
  unsigned char *p;
2916
161
  unsigned int total_reloc_size = 0;
2917
161
  unsigned int subspace_reloc_size = 0;
2918
161
  unsigned int num_spaces = obj_som_file_hdr (abfd)->space_total;
2919
161
  asection *section = abfd->sections;
2920
161
  size_t amt;
2921
2922
161
  memset (tmp_space, 0, SOM_TMP_BUFSIZE);
2923
161
  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
249
  for (i = 0; i < num_spaces; i++)
2933
122
    {
2934
122
      asection *subsection;
2935
2936
      /* Find a space.  */
2937
135
      while (section && !som_is_space (section))
2938
13
  section = section->next;
2939
122
      if (!section)
2940
0
  break;
2941
2942
      /* Now iterate through each of its subspaces.  */
2943
122
      for (subsection = abfd->sections;
2944
461
     subsection != NULL;
2945
339
     subsection = subsection->next)
2946
373
  {
2947
373
    unsigned int reloc_offset;
2948
373
    unsigned int current_rounding_mode;
2949
373
#ifndef NO_PCREL_MODES
2950
373
    unsigned int current_call_mode;
2951
373
#endif
2952
2953
    /* Find a subspace of this space.  */
2954
373
    if (!som_is_subspace (subsection)
2955
105
        || !som_is_container (section, subsection))
2956
303
      continue;
2957
2958
    /* If this subspace does not have real data, then we are
2959
       finished with it.  */
2960
70
    if ((subsection->flags & SEC_HAS_CONTENTS) == 0)
2961
17
      {
2962
17
        som_section_data (subsection)->subspace_dict->fixup_request_index
2963
17
    = -1;
2964
17
        continue;
2965
17
      }
2966
2967
    /* This subspace has some relocations.  Put the relocation stream
2968
       index into the subspace record.  */
2969
53
    som_section_data (subsection)->subspace_dict->fixup_request_index
2970
53
      = 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
53
    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
53
    p = tmp_space;
2982
53
    subspace_reloc_size = 0;
2983
53
    reloc_offset = 0;
2984
53
    som_initialize_reloc_queue (reloc_queue);
2985
53
    current_rounding_mode = R_N_MODE;
2986
53
#ifndef NO_PCREL_MODES
2987
53
    current_call_mode = R_SHORT_PCREL_MODE;
2988
53
#endif
2989
2990
    /* Translate each BFD relocation into one or more SOM
2991
       relocations.  */
2992
1.24k
    for (j = 0; j < subsection->reloc_count; j++)
2993
1.22k
      {
2994
1.22k
        arelent *bfd_reloc = subsection->orelocation[j];
2995
1.22k
        unsigned int skip;
2996
1.22k
        int sym_num;
2997
2998
1.22k
        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
1.22k
        if (!bfd_reloc_offset_in_range (bfd_reloc->howto,
3010
1.22k
                abfd, subsection,
3011
1.22k
                bfd_reloc->address))
3012
34
    {
3013
34
      _bfd_error_handler
3014
        /* xgettext:c-format */
3015
34
        (_("%pB(%pA+%#" PRIx64 "): "
3016
34
           "%s relocation offset out of range"),
3017
34
         abfd, subsection, (uint64_t) bfd_reloc->address,
3018
34
         bfd_reloc->howto->name);
3019
34
      bfd_set_error (bfd_error_bad_value);
3020
34
      return false;
3021
34
    }
3022
3023
        /* Get the symbol number.  Remember it's stored in a
3024
     special place for section symbols.  */
3025
1.19k
        if ((*bfd_reloc->sym_ptr_ptr)->flags & BSF_SECTION_SYM)
3026
1.14k
    sym_num = (*bfd_reloc->sym_ptr_ptr)->udata.i;
3027
47
        else
3028
47
    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
1.19k
        if (p - tmp_space + 512 > SOM_TMP_BUFSIZE)
3040
0
    {
3041
0
      amt = p - tmp_space;
3042
0
      if (bfd_write (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
1.19k
        skip = bfd_reloc->address - reloc_offset;
3052
1.19k
        p = som_reloc_skip (abfd, skip, p,
3053
1.19k
          &subspace_reloc_size, reloc_queue);
3054
3055
        /* Update reloc_offset for the next iteration.  */
3056
1.19k
        reloc_offset = bfd_reloc->address + bfd_reloc->howto->size;
3057
3058
        /* Now the actual relocation we care about.  */
3059
1.19k
        switch (bfd_reloc->howto->type)
3060
1.19k
    {
3061
141
    case R_PCREL_CALL:
3062
169
    case R_ABS_CALL:
3063
169
      p = som_reloc_call (abfd, p, &subspace_reloc_size,
3064
169
              bfd_reloc, sym_num, reloc_queue);
3065
169
      break;
3066
3067
94
    case R_CODE_ONE_SYMBOL:
3068
289
    case R_DP_RELATIVE:
3069
      /* Account for any addend.  */
3070
289
      if (bfd_reloc->addend)
3071
22
        p = som_reloc_addend (abfd, bfd_reloc->addend, p,
3072
22
            &subspace_reloc_size, reloc_queue);
3073
3074
289
      if (sym_num < 0x20)
3075
289
        {
3076
289
          bfd_put_8 (abfd, bfd_reloc->howto->type + sym_num, p);
3077
289
          subspace_reloc_size += 1;
3078
289
          p += 1;
3079
289
        }
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
289
      break;
3098
3099
289
    case R_DATA_GPREL:
3100
      /* Account for any addend.  */
3101
27
      if (bfd_reloc->addend)
3102
11
        p = som_reloc_addend (abfd, bfd_reloc->addend, p,
3103
11
            &subspace_reloc_size, reloc_queue);
3104
3105
27
      if (sym_num < 0x10000000)
3106
27
        {
3107
27
          bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3108
27
          bfd_put_8 (abfd, sym_num >> 16, p + 1);
3109
27
          bfd_put_16 (abfd, (bfd_vma) sym_num, p + 2);
3110
27
          p = try_prev_fixup (abfd, &subspace_reloc_size,
3111
27
            p, 4, reloc_queue);
3112
27
        }
3113
0
      else
3114
0
        abort ();
3115
27
      break;
3116
3117
27
    case R_DATA_ONE_SYMBOL:
3118
27
    case R_DATA_PLABEL:
3119
30
    case R_CODE_PLABEL:
3120
74
    case R_DLT_REL:
3121
      /* Account for any addend using R_DATA_OVERRIDE.  */
3122
74
      if (bfd_reloc->howto->type != R_DATA_ONE_SYMBOL
3123
60
          && bfd_reloc->addend)
3124
7
        p = som_reloc_addend (abfd, bfd_reloc->addend, p,
3125
7
            &subspace_reloc_size, reloc_queue);
3126
3127
74
      if (sym_num < 0x100)
3128
74
        {
3129
74
          bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3130
74
          bfd_put_8 (abfd, sym_num, p + 1);
3131
74
          p = try_prev_fixup (abfd, &subspace_reloc_size, p,
3132
74
            2, reloc_queue);
3133
74
        }
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
74
      break;
3145
3146
74
    case R_ENTRY:
3147
3
      {
3148
3
        unsigned int tmp;
3149
3
        arelent *tmp_reloc = NULL;
3150
3
        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
3
        bfd_put_32 (abfd, bfd_reloc->addend, p + 1);
3159
3160
        /* Find the next R_EXIT relocation.  */
3161
14
        for (tmp = j; tmp < subsection->reloc_count; tmp++)
3162
14
          {
3163
14
      tmp_reloc = subsection->orelocation[tmp];
3164
14
      if (tmp_reloc->howto->type == R_EXIT)
3165
3
        break;
3166
14
          }
3167
3168
3
        if (tmp == subsection->reloc_count)
3169
0
          abort ();
3170
3171
3
        bfd_put_32 (abfd, tmp_reloc->addend, p + 5);
3172
3
        p = try_prev_fixup (abfd, &subspace_reloc_size,
3173
3
          p, 9, reloc_queue);
3174
3
        break;
3175
3
      }
3176
3177
3
    case R_N_MODE:
3178
4
    case R_S_MODE:
3179
9
    case R_D_MODE:
3180
14
    case R_R_MODE:
3181
      /* If this relocation requests the current rounding
3182
         mode, then it is redundant.  */
3183
14
      if (bfd_reloc->howto->type != current_rounding_mode)
3184
7
        {
3185
7
          bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3186
7
          subspace_reloc_size += 1;
3187
7
          p += 1;
3188
7
          current_rounding_mode = bfd_reloc->howto->type;
3189
7
        }
3190
14
      break;
3191
3192
0
#ifndef NO_PCREL_MODES
3193
14
    case R_LONG_PCREL_MODE:
3194
38
    case R_SHORT_PCREL_MODE:
3195
38
      if (bfd_reloc->howto->type != current_call_mode)
3196
6
        {
3197
6
          bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3198
6
          subspace_reloc_size += 1;
3199
6
          p += 1;
3200
6
          current_call_mode = bfd_reloc->howto->type;
3201
6
        }
3202
38
      break;
3203
0
#endif
3204
3205
6
    case R_EXIT:
3206
8
    case R_ALT_ENTRY:
3207
8
    case R_FSEL:
3208
60
    case R_LSEL:
3209
62
    case R_RSEL:
3210
66
    case R_BEGIN_BRTAB:
3211
67
    case R_END_BRTAB:
3212
133
    case R_BEGIN_TRY:
3213
136
    case R_N0SEL:
3214
208
    case R_N1SEL:
3215
208
      bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3216
208
      subspace_reloc_size += 1;
3217
208
      p += 1;
3218
208
      break;
3219
3220
12
    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
12
      if (bfd_reloc->addend == 0)
3225
5
        bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3226
7
      else if (bfd_reloc->addend < 1024)
3227
2
        {
3228
2
          bfd_put_8 (abfd, bfd_reloc->howto->type + 1, p);
3229
2
          bfd_put_8 (abfd, bfd_reloc->addend / 4, p + 1);
3230
2
          p = try_prev_fixup (abfd, &subspace_reloc_size,
3231
2
            p, 2, reloc_queue);
3232
2
        }
3233
5
      else
3234
5
        {
3235
5
          bfd_put_8 (abfd, bfd_reloc->howto->type + 2, p);
3236
5
          bfd_put_8 (abfd, (bfd_reloc->addend / 4) >> 16, p + 1);
3237
5
          bfd_put_16 (abfd, bfd_reloc->addend / 4, p + 2);
3238
5
          p = try_prev_fixup (abfd, &subspace_reloc_size,
3239
5
            p, 4, reloc_queue);
3240
5
        }
3241
12
      break;
3242
3243
3
    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
3
      bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3248
3
      bfd_put_8 (abfd, 0x44, p + 1);
3249
3
      p = try_prev_fixup (abfd, &subspace_reloc_size,
3250
3
              p, 2, reloc_queue);
3251
3
      break;
3252
3253
15
    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
15
      bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3258
15
      bfd_put_8 (abfd, 0x80, p + 1);
3259
15
      bfd_put_8 (abfd, sym_num >> 16, p + 2);
3260
15
      bfd_put_16 (abfd, (bfd_vma) sym_num, p + 3);
3261
15
      p = try_prev_fixup (abfd, &subspace_reloc_size,
3262
15
              p, 5, reloc_queue);
3263
15
      break;
3264
3265
9
    case R_CODE_EXPR:
3266
47
    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
47
      bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3271
47
      subspace_reloc_size += 1;
3272
47
      p += 1;
3273
47
      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
292
    default:
3279
292
      bfd_put_8 (abfd, 0xff, p);
3280
292
      subspace_reloc_size += 1;
3281
292
      p += 1;
3282
292
      break;
3283
1.19k
    }
3284
1.19k
      }
3285
3286
    /* Last BFD relocation for a subspace has been processed.
3287
       Map the rest of the subspace with R_NO_RELOCATION fixups.  */
3288
19
    p = som_reloc_skip (abfd, subsection->size - reloc_offset,
3289
19
            p, &subspace_reloc_size, reloc_queue);
3290
3291
    /* Scribble out the relocations.  */
3292
19
    amt = p - tmp_space;
3293
19
    if (bfd_write (tmp_space, amt, abfd) != amt)
3294
0
      return false;
3295
19
    p = tmp_space;
3296
3297
19
    total_reloc_size += subspace_reloc_size;
3298
19
    som_section_data (subsection)->subspace_dict->fixup_request_quantity
3299
19
      = subspace_reloc_size;
3300
19
  }
3301
88
      section = section->next;
3302
88
    }
3303
127
  *total_reloc_sizep = total_reloc_size;
3304
127
  return true;
3305
161
}
3306
3307
/* Write the length of STR followed by STR to P which points into
3308
   *BUF, a buffer of *BUFLEN size.  Track total size in *STRINGS_SIZE,
3309
   setting *STRX to the current offset for STR.  When STR can't fit in
3310
   *BUF, flush the buffer to ABFD, possibly reallocating.  Return the
3311
   next available location in *BUF, or NULL on error.  */
3312
3313
static char *
3314
add_string (char *p, const char *str, bfd *abfd, char **buf, size_t *buflen,
3315
      unsigned int *strings_size, unsigned int *strx)
3316
453
{
3317
453
  size_t length = strlen (str) + 1;
3318
  /* Each entry will take 4 bytes to hold the string length + the
3319
     string itself + null terminator + padding to a 4 byte boundary.  */
3320
453
  size_t needed = (4 + length + 3) & ~3;
3321
3322
  /* If there is not enough room for the next entry, then dump the
3323
     current buffer contents now and maybe allocate a larger buffer.  */
3324
453
  if (p - *buf + needed > *buflen)
3325
0
    {
3326
      /* Flush buffer before refilling or reallocating.  */
3327
0
      size_t amt = p - *buf;
3328
0
      if (bfd_write (*buf, amt, abfd) != amt)
3329
0
  return NULL;
3330
3331
      /* Reallocate if now empty buffer still too small.  */
3332
0
      if (needed > *buflen)
3333
0
  {
3334
    /* Ensure a minimum growth factor to avoid O(n**2) space
3335
       consumption for n strings.  The optimal minimum factor
3336
       seems to be 2.  */
3337
0
    if (*buflen * 2 < needed)
3338
0
      *buflen = needed;
3339
0
    else
3340
0
      *buflen = *buflen * 2;
3341
0
    free (*buf);
3342
0
    *buf = bfd_malloc (*buflen);
3343
0
    if (*buf == NULL)
3344
0
      return NULL;
3345
0
  }
3346
3347
      /* Reset to beginning of the (possibly new) buffer space.  */
3348
0
      p = *buf;
3349
0
    }
3350
3351
  /* First element in a string table entry is the length of
3352
     the string.  This must always be 4 byte aligned.  This is
3353
     also an appropriate time to fill in the string index
3354
     field in the symbol table entry.  */
3355
453
  bfd_put_32 (abfd, length - 1, p);
3356
453
  *strings_size += 4;
3357
453
  p += 4;
3358
3359
453
  *strx = *strings_size;
3360
3361
  /* Next comes the string itself + a null terminator.  */
3362
453
  memcpy (p, str, length);
3363
453
  p += length;
3364
453
  *strings_size += length;
3365
3366
  /* Always align up to the next word boundary.  */
3367
453
  if (length & 3)
3368
177
    {
3369
177
      length = 4 - (length & 3);
3370
177
      memset (p, 0, length);
3371
177
      *strings_size += length;
3372
177
      p += length;
3373
177
    }
3374
453
  return p;
3375
453
}
3376
3377
/* Write out the space/subspace string table.  */
3378
3379
static bool
3380
som_write_space_strings (bfd *abfd,
3381
       unsigned long current_offset,
3382
       unsigned int *strings_size)
3383
161
{
3384
  /* Chunk of memory that we can use as buffer space, then throw
3385
     away.  */
3386
161
  size_t tmp_space_size = SOM_TMP_BUFSIZE;
3387
161
  char *tmp_space = bfd_malloc (tmp_space_size);
3388
161
  char *p = tmp_space;
3389
161
  asection *section;
3390
3391
161
  if (tmp_space == NULL)
3392
0
    return false;
3393
3394
  /* Seek to the start of the space strings in preparation for writing
3395
     them out.  */
3396
161
  if (bfd_seek (abfd, current_offset, SEEK_SET) != 0)
3397
0
    return false;
3398
3399
  /* Walk through all the spaces and subspaces (order is not important)
3400
     building up and writing string table entries for their names.  */
3401
161
  *strings_size = 0;
3402
368
  for (section = abfd->sections; section != NULL; section = section->next)
3403
207
    {
3404
207
      unsigned int *strx;
3405
3406
      /* Only work with space/subspaces; avoid any other sections
3407
   which might have been made (.text for example).  */
3408
207
      if (som_is_space (section))
3409
137
  strx = &som_section_data (section)->space_dict->name;
3410
70
      else if (som_is_subspace (section))
3411
70
  strx = &som_section_data (section)->subspace_dict->name;
3412
0
      else
3413
0
  continue;
3414
3415
207
      p = add_string (p, section->name, abfd, &tmp_space, &tmp_space_size,
3416
207
          strings_size, strx);
3417
207
      if (p == NULL)
3418
0
  return false;
3419
207
    }
3420
3421
  /* Done with the space/subspace strings.  Write out any information
3422
     contained in a partial block.  */
3423
161
  size_t amt = p - tmp_space;
3424
161
  bool ok = amt ? bfd_write (tmp_space, amt, abfd) == amt : true;
3425
161
  free (tmp_space);
3426
161
  return ok;
3427
161
}
3428
3429
/* Write out the symbol string table.  */
3430
3431
static bool
3432
som_write_symbol_strings (bfd *abfd,
3433
        unsigned long current_offset,
3434
        asymbol **syms,
3435
        unsigned int num_syms,
3436
        unsigned int *strings_size,
3437
        struct som_compilation_unit *compilation_unit)
3438
161
{
3439
161
  unsigned int i;
3440
  /* Chunk of memory that we can use as buffer space, then throw
3441
     away.  */
3442
161
  size_t tmp_space_size = SOM_TMP_BUFSIZE;
3443
161
  char *tmp_space = bfd_malloc (tmp_space_size);
3444
161
  char *p = tmp_space;
3445
3446
161
  if (tmp_space == NULL)
3447
0
    return false;
3448
3449
  /* This gets a bit gruesome because of the compilation unit.  The
3450
     strings within the compilation unit are part of the symbol
3451
     strings, but don't have symbol_dictionary entries.  So, manually
3452
     write them and update the compilation unit header.  On input, the
3453
     compilation unit header contains local copies of the strings.
3454
     Move them aside.  */
3455
3456
  /* Seek to the start of the space strings in preparation for writing
3457
     them out.  */
3458
161
  if (bfd_seek (abfd, current_offset, SEEK_SET) != 0)
3459
0
    return false;
3460
3461
161
  *strings_size = 0;
3462
161
  if (compilation_unit)
3463
0
    {
3464
0
      for (i = 0; i < 4; i++)
3465
0
  {
3466
0
    struct som_name_pt *name;
3467
3468
0
    switch (i)
3469
0
      {
3470
0
      case 0:
3471
0
        name = &compilation_unit->name;
3472
0
        break;
3473
0
      case 1:
3474
0
        name = &compilation_unit->language_name;
3475
0
        break;
3476
0
      case 2:
3477
0
        name = &compilation_unit->product_id;
3478
0
        break;
3479
0
      case 3:
3480
0
        name = &compilation_unit->version_id;
3481
0
        break;
3482
0
      default:
3483
0
        abort ();
3484
0
      }
3485
3486
0
    p = add_string (p, name->name, abfd, &tmp_space, &tmp_space_size,
3487
0
        strings_size, &name->strx);
3488
3489
0
    if (p == NULL)
3490
0
      return false;
3491
0
  }
3492
0
    }
3493
3494
407
  for (i = 0; i < num_syms; i++)
3495
246
    {
3496
246
      p = add_string (p, syms[i]->name, abfd, &tmp_space, &tmp_space_size,
3497
246
          strings_size,
3498
246
          &som_symbol_data (syms[i])->stringtab_offset);
3499
246
      if (p == NULL)
3500
0
  return false;
3501
246
    }
3502
3503
  /* Scribble out any partial block.  */
3504
161
  size_t amt = p - tmp_space;
3505
161
  bool ok = amt ? bfd_write (tmp_space, amt, abfd) == amt : true;
3506
161
  free (tmp_space);
3507
161
  return ok;
3508
161
}
3509
3510
/* Compute variable information to be placed in the SOM headers,
3511
   space/subspace dictionaries, relocation streams, etc.  Begin
3512
   writing parts of the object file.  */
3513
3514
static bool
3515
som_begin_writing (bfd *abfd)
3516
161
{
3517
161
  unsigned long current_offset = 0;
3518
161
  unsigned int strings_size = 0;
3519
161
  unsigned long num_spaces, num_subspaces, i;
3520
161
  asection *section;
3521
161
  unsigned int total_subspaces = 0;
3522
161
  struct som_exec_auxhdr *exec_header = NULL;
3523
3524
  /* The file header will always be first in an object file,
3525
     everything else can be in random locations.  To keep things
3526
     "simple" BFD will lay out the object file in the manner suggested
3527
     by the PRO ABI for PA-RISC Systems.  */
3528
3529
  /* Before any output can really begin offsets for all the major
3530
     portions of the object file must be computed.  So, starting
3531
     with the initial file header compute (and sometimes write)
3532
     each portion of the object file.  */
3533
3534
  /* Make room for the file header, it's contents are not complete
3535
     yet, so it can not be written at this time.  */
3536
161
  current_offset += sizeof (struct som_external_header);
3537
3538
  /* Any auxiliary headers will follow the file header.  Right now
3539
     we support only the copyright and version headers.  */
3540
161
  obj_som_file_hdr (abfd)->aux_header_location = current_offset;
3541
161
  obj_som_file_hdr (abfd)->aux_header_size = 0;
3542
161
  if (abfd->flags & (EXEC_P | DYNAMIC))
3543
138
    {
3544
      /* Parts of the exec header will be filled in later, so
3545
   delay writing the header itself.  Fill in the defaults,
3546
   and write it later.  */
3547
138
      current_offset += sizeof (struct som_external_exec_auxhdr);
3548
138
      obj_som_file_hdr (abfd)->aux_header_size
3549
138
  += sizeof (struct som_external_exec_auxhdr);
3550
138
      exec_header = obj_som_exec_hdr (abfd);
3551
138
      exec_header->som_auxhdr.type = EXEC_AUX_ID;
3552
138
      exec_header->som_auxhdr.length = 40;
3553
138
    }
3554
161
  if (obj_som_version_hdr (abfd) != NULL)
3555
0
    {
3556
0
      struct som_external_string_auxhdr ext_string_auxhdr;
3557
0
      bfd_size_type len;
3558
3559
0
      if (bfd_seek (abfd, current_offset, SEEK_SET) != 0)
3560
0
  return false;
3561
3562
      /* Write the aux_id structure and the string length.  */
3563
0
      len = sizeof (struct som_external_string_auxhdr);
3564
0
      obj_som_file_hdr (abfd)->aux_header_size += len;
3565
0
      current_offset += len;
3566
0
      som_swap_string_auxhdr_out
3567
0
  (obj_som_version_hdr (abfd), &ext_string_auxhdr);
3568
0
      if (bfd_write (&ext_string_auxhdr, len, abfd) != len)
3569
0
  return false;
3570
3571
      /* Write the version string.  */
3572
0
      len = obj_som_version_hdr (abfd)->header_id.length - 4;
3573
0
      obj_som_file_hdr (abfd)->aux_header_size += len;
3574
0
      current_offset += len;
3575
0
      if (bfd_write (obj_som_version_hdr (abfd)->string, len, abfd) != len)
3576
0
  return false;
3577
0
    }
3578
3579
161
  if (obj_som_copyright_hdr (abfd) != NULL)
3580
0
    {
3581
0
      struct som_external_string_auxhdr ext_string_auxhdr;
3582
0
      bfd_size_type len;
3583
3584
0
      if (bfd_seek (abfd, current_offset, SEEK_SET) != 0)
3585
0
  return false;
3586
3587
      /* Write the aux_id structure and the string length.  */
3588
0
      len = sizeof (struct som_external_string_auxhdr);
3589
0
      obj_som_file_hdr (abfd)->aux_header_size += len;
3590
0
      current_offset += len;
3591
0
      som_swap_string_auxhdr_out
3592
0
  (obj_som_copyright_hdr (abfd), &ext_string_auxhdr);
3593
0
      if (bfd_write (&ext_string_auxhdr, len, abfd) != len)
3594
0
  return false;
3595
3596
      /* Write the copyright string.  */
3597
0
      len = obj_som_copyright_hdr (abfd)->header_id.length - 4;
3598
0
      obj_som_file_hdr (abfd)->aux_header_size += len;
3599
0
      current_offset += len;
3600
0
      if (bfd_write (obj_som_copyright_hdr (abfd)->string, len, abfd) != len)
3601
0
  return false;
3602
0
    }
3603
3604
  /* Next comes the initialization pointers; we have no initialization
3605
     pointers, so current offset does not change.  */
3606
161
  obj_som_file_hdr (abfd)->init_array_location = current_offset;
3607
161
  obj_som_file_hdr (abfd)->init_array_total = 0;
3608
3609
  /* Next are the space records.  These are fixed length records.
3610
3611
     Count the number of spaces to determine how much room is needed
3612
     in the object file for the space records.
3613
3614
     The names of the spaces are stored in a separate string table,
3615
     and the index for each space into the string table is computed
3616
     below.  Therefore, it is not possible to write the space headers
3617
     at this time.  */
3618
161
  num_spaces = som_count_spaces (abfd);
3619
161
  obj_som_file_hdr (abfd)->space_location = current_offset;
3620
161
  obj_som_file_hdr (abfd)->space_total = num_spaces;
3621
161
  current_offset +=
3622
161
    num_spaces * sizeof (struct som_external_space_dictionary_record);
3623
3624
  /* Next are the subspace records.  These are fixed length records.
3625
3626
     Count the number of subspaes to determine how much room is needed
3627
     in the object file for the subspace records.
3628
3629
     A variety if fields in the subspace record are still unknown at
3630
     this time (index into string table, fixup stream location/size, etc).  */
3631
161
  num_subspaces = som_count_subspaces (abfd);
3632
161
  obj_som_file_hdr (abfd)->subspace_location = current_offset;
3633
161
  obj_som_file_hdr (abfd)->subspace_total = num_subspaces;
3634
161
  current_offset
3635
161
    += num_subspaces * sizeof (struct som_external_subspace_dictionary_record);
3636
3637
  /* Next is the string table for the space/subspace names.  We will
3638
     build and write the string table on the fly.  At the same time
3639
     we will fill in the space/subspace name index fields.  */
3640
3641
  /* The string table needs to be aligned on a word boundary.  */
3642
161
  if (current_offset % 4)
3643
0
    current_offset += (4 - (current_offset % 4));
3644
3645
  /* Mark the offset of the space/subspace string table in the
3646
     file header.  */
3647
161
  obj_som_file_hdr (abfd)->space_strings_location = current_offset;
3648
3649
  /* Scribble out the space strings.  */
3650
161
  if (! som_write_space_strings (abfd, current_offset, &strings_size))
3651
0
    return false;
3652
3653
  /* Record total string table size in the header and update the
3654
     current offset.  */
3655
161
  obj_som_file_hdr (abfd)->space_strings_size = strings_size;
3656
161
  current_offset += strings_size;
3657
3658
  /* Next is the compilation unit.  */
3659
161
  obj_som_file_hdr (abfd)->compiler_location = current_offset;
3660
161
  obj_som_file_hdr (abfd)->compiler_total = 0;
3661
161
  if (obj_som_compilation_unit (abfd))
3662
0
    {
3663
0
      obj_som_file_hdr (abfd)->compiler_total = 1;
3664
0
      current_offset += sizeof (struct som_external_compilation_unit);
3665
0
    }
3666
3667
  /* Now compute the file positions for the loadable subspaces, taking
3668
     care to make sure everything stays properly aligned.  */
3669
3670
161
  section = abfd->sections;
3671
298
  for (i = 0; i < num_spaces; i++)
3672
137
    {
3673
137
      asection *subsection;
3674
137
      int first_subspace;
3675
137
      unsigned int subspace_offset = 0;
3676
3677
      /* Find a space.  */
3678
180
      while (!som_is_space (section))
3679
43
  section = section->next;
3680
3681
137
      first_subspace = 1;
3682
      /* Now look for all its subspaces.  */
3683
137
      for (subsection = abfd->sections;
3684
585
     subsection != NULL;
3685
448
     subsection = subsection->next)
3686
448
  {
3687
3688
448
    if (!som_is_subspace (subsection)
3689
135
        || !som_is_container (section, subsection)
3690
70
        || (subsection->flags & SEC_ALLOC) == 0)
3691
430
      continue;
3692
3693
    /* If this is the first subspace in the space, and we are
3694
       building an executable, then take care to make sure all
3695
       the alignments are correct and update the exec header.  */
3696
18
    if (first_subspace
3697
18
        && (abfd->flags & (EXEC_P | DYNAMIC)))
3698
10
      {
3699
        /* Demand paged executables have each space aligned to a
3700
     page boundary.  Sharable executables (write-protected
3701
     text) have just the private (aka data & bss) space aligned
3702
     to a page boundary.  Ugh.  Not true for HPUX.
3703
3704
     The HPUX kernel requires the text to always be page aligned
3705
     within the file regardless of the executable's type.  */
3706
10
        if (abfd->flags & (D_PAGED | DYNAMIC)
3707
0
      || (subsection->flags & SEC_CODE)
3708
0
      || ((abfd->flags & WP_TEXT)
3709
0
          && (subsection->flags & SEC_DATA)))
3710
10
    current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
3711
3712
        /* Update the exec header.  */
3713
10
        if (subsection->flags & SEC_CODE && exec_header->exec_tfile == 0)
3714
7
    {
3715
7
      exec_header->exec_tmem = section->vma;
3716
7
      exec_header->exec_tfile = current_offset;
3717
7
    }
3718
10
        if (subsection->flags & SEC_DATA && exec_header->exec_dfile == 0)
3719
7
    {
3720
7
      exec_header->exec_dmem = section->vma;
3721
7
      exec_header->exec_dfile = current_offset;
3722
7
    }
3723
3724
        /* Keep track of exactly where we are within a particular
3725
     space.  This is necessary as the braindamaged HPUX
3726
     loader will create holes between subspaces *and*
3727
     subspace alignments are *NOT* preserved.  What a crock.  */
3728
10
        subspace_offset = subsection->vma;
3729
3730
        /* Only do this for the first subspace within each space.  */
3731
10
        first_subspace = 0;
3732
10
      }
3733
8
    else if (abfd->flags & (EXEC_P | DYNAMIC))
3734
0
      {
3735
        /* The braindamaged HPUX loader may have created a hole
3736
     between two subspaces.  It is *not* sufficient to use
3737
     the alignment specifications within the subspaces to
3738
     account for these holes -- I've run into at least one
3739
     case where the loader left one code subspace unaligned
3740
     in a final executable.
3741
3742
     To combat this we keep a current offset within each space,
3743
     and use the subspace vma fields to detect and preserve
3744
     holes.  What a crock!
3745
3746
     ps.  This is not necessary for unloadable space/subspaces.  */
3747
0
        current_offset += subsection->vma - subspace_offset;
3748
0
        if (subsection->flags & SEC_CODE)
3749
0
    exec_header->exec_tsize += subsection->vma - subspace_offset;
3750
0
        else
3751
0
    exec_header->exec_dsize += subsection->vma - subspace_offset;
3752
0
        subspace_offset += subsection->vma - subspace_offset;
3753
0
      }
3754
3755
18
    subsection->target_index = total_subspaces++;
3756
    /* This is real data to be loaded from the file.  */
3757
18
    if (subsection->flags & SEC_LOAD)
3758
14
      {
3759
        /* Update the size of the code & data.  */
3760
14
        if (abfd->flags & (EXEC_P | DYNAMIC)
3761
9
      && subsection->flags & SEC_CODE)
3762
6
    exec_header->exec_tsize += subsection->size;
3763
8
        else if (abfd->flags & (EXEC_P | DYNAMIC)
3764
3
           && subsection->flags & SEC_DATA)
3765
3
    exec_header->exec_dsize += subsection->size;
3766
14
        som_section_data (subsection)->subspace_dict->file_loc_init_value
3767
14
    = current_offset;
3768
14
        subsection->filepos = current_offset;
3769
14
        current_offset += subsection->size;
3770
14
        subspace_offset += subsection->size;
3771
14
      }
3772
    /* Looks like uninitialized data.  */
3773
4
    else
3774
4
      {
3775
        /* Update the size of the bss section.  */
3776
4
        if (abfd->flags & (EXEC_P | DYNAMIC))
3777
1
    exec_header->exec_bsize += subsection->size;
3778
3779
4
        som_section_data (subsection)->subspace_dict->file_loc_init_value
3780
4
    = 0;
3781
4
        som_section_data (subsection)->subspace_dict->
3782
4
    initialization_length = 0;
3783
4
      }
3784
18
  }
3785
      /* Goto the next section.  */
3786
137
      section = section->next;
3787
137
    }
3788
3789
  /* Finally compute the file positions for unloadable subspaces.
3790
     If building an executable, start the unloadable stuff on its
3791
     own page.  */
3792
3793
161
  if (abfd->flags & (EXEC_P | DYNAMIC))
3794
138
    current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
3795
3796
161
  obj_som_file_hdr (abfd)->unloadable_sp_location = current_offset;
3797
161
  section = abfd->sections;
3798
298
  for (i = 0; i < num_spaces; i++)
3799
137
    {
3800
137
      asection *subsection;
3801
3802
      /* Find a space.  */
3803
180
      while (!som_is_space (section))
3804
43
  section = section->next;
3805
3806
137
      if (abfd->flags & (EXEC_P | DYNAMIC))
3807
109
  current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
3808
3809
      /* Now look for all its subspaces.  */
3810
137
      for (subsection = abfd->sections;
3811
585
     subsection != NULL;
3812
448
     subsection = subsection->next)
3813
448
  {
3814
3815
448
    if (!som_is_subspace (subsection)
3816
135
        || !som_is_container (section, subsection)
3817
70
        || (subsection->flags & SEC_ALLOC) != 0)
3818
396
      continue;
3819
3820
52
    subsection->target_index = total_subspaces++;
3821
    /* This is real data to be loaded from the file.  */
3822
52
    if ((subsection->flags & SEC_LOAD) == 0)
3823
52
      {
3824
52
        som_section_data (subsection)->subspace_dict->file_loc_init_value
3825
52
    = current_offset;
3826
52
        subsection->filepos = current_offset;
3827
52
        current_offset += subsection->size;
3828
52
      }
3829
    /* Looks like uninitialized data.  */
3830
0
    else
3831
0
      {
3832
0
        som_section_data (subsection)->subspace_dict->file_loc_init_value
3833
0
    = 0;
3834
0
        som_section_data (subsection)->subspace_dict->
3835
0
    initialization_length = subsection->size;
3836
0
      }
3837
52
  }
3838
      /* Goto the next section.  */
3839
137
      section = section->next;
3840
137
    }
3841
3842
  /* If building an executable, then make sure to seek to and write
3843
     one byte at the end of the file to make sure any necessary
3844
     zeros are filled in.  Ugh.  */
3845
161
  if (abfd->flags & (EXEC_P | DYNAMIC))
3846
138
    current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
3847
161
  if (bfd_seek (abfd, current_offset - 1, SEEK_SET) != 0)
3848
0
    return false;
3849
161
  if (bfd_write ("", 1, abfd) != 1)
3850
0
    return false;
3851
3852
161
  obj_som_file_hdr (abfd)->unloadable_sp_size
3853
161
    = current_offset - obj_som_file_hdr (abfd)->unloadable_sp_location;
3854
3855
  /* Loader fixups are not supported in any way shape or form.  */
3856
161
  obj_som_file_hdr (abfd)->loader_fixup_location = 0;
3857
161
  obj_som_file_hdr (abfd)->loader_fixup_total = 0;
3858
3859
  /* Done.  Store the total size of the SOM so far.  */
3860
161
  obj_som_file_hdr (abfd)->som_length = current_offset;
3861
3862
161
  return true;
3863
161
}
3864
3865
/* Finally, scribble out the various headers to the disk.  */
3866
3867
static bool
3868
som_finish_writing (bfd *abfd)
3869
161
{
3870
161
  int num_spaces = som_count_spaces (abfd);
3871
161
  asymbol **syms = bfd_get_outsymbols (abfd);
3872
161
  int i, num_syms;
3873
161
  int subspace_index = 0;
3874
161
  file_ptr location;
3875
161
  asection *section;
3876
161
  unsigned long current_offset;
3877
161
  unsigned int strings_size, total_reloc_size;
3878
161
  size_t amt;
3879
161
  struct som_external_header ext_header;
3880
3881
  /* We must set up the version identifier here as objcopy/strip copy
3882
     private BFD data too late for us to handle this in som_begin_writing.  */
3883
161
  if (obj_som_exec_data (abfd)
3884
161
      && obj_som_exec_data (abfd)->version_id)
3885
161
    obj_som_file_hdr (abfd)->version_id = obj_som_exec_data (abfd)->version_id;
3886
0
  else
3887
0
    obj_som_file_hdr (abfd)->version_id = NEW_VERSION_ID;
3888
3889
  /* Next is the symbol table.  These are fixed length records.
3890
3891
     Count the number of symbols to determine how much room is needed
3892
     in the object file for the symbol table.
3893
3894
     The names of the symbols are stored in a separate string table,
3895
     and the index for each symbol name into the string table is computed
3896
     below.  Therefore, it is not possible to write the symbol table
3897
     at this time.
3898
3899
     These used to be output before the subspace contents, but they
3900
     were moved here to work around a stupid bug in the hpux linker
3901
     (fixed in hpux10).  */
3902
161
  current_offset = obj_som_file_hdr (abfd)->som_length;
3903
3904
  /* Make sure we're on a word boundary.  */
3905
161
  if (current_offset % 4)
3906
8
    current_offset += (4 - (current_offset % 4));
3907
3908
161
  num_syms = bfd_get_symcount (abfd);
3909
161
  obj_som_file_hdr (abfd)->symbol_location = current_offset;
3910
161
  obj_som_file_hdr (abfd)->symbol_total = num_syms;
3911
161
  current_offset +=
3912
161
    num_syms * sizeof (struct som_external_symbol_dictionary_record);
3913
3914
  /* Next are the symbol strings.
3915
     Align them to a word boundary.  */
3916
161
  if (current_offset % 4)
3917
0
    current_offset += (4 - (current_offset % 4));
3918
161
  obj_som_file_hdr (abfd)->symbol_strings_location = current_offset;
3919
3920
  /* Scribble out the symbol strings.  */
3921
161
  if (! som_write_symbol_strings (abfd, current_offset, syms,
3922
161
          num_syms, &strings_size,
3923
161
          obj_som_compilation_unit (abfd)))
3924
0
    return false;
3925
3926
  /* Record total string table size in header and update the
3927
     current offset.  */
3928
161
  obj_som_file_hdr (abfd)->symbol_strings_size = strings_size;
3929
161
  current_offset += strings_size;
3930
3931
  /* Do prep work before handling fixups.  */
3932
161
  if (!som_prep_for_fixups (abfd,
3933
161
          bfd_get_outsymbols (abfd),
3934
161
          bfd_get_symcount (abfd)))
3935
0
    return false;
3936
3937
  /* At the end of the file is the fixup stream which starts on a
3938
     word boundary.  */
3939
161
  if (current_offset % 4)
3940
0
    current_offset += (4 - (current_offset % 4));
3941
161
  obj_som_file_hdr (abfd)->fixup_request_location = current_offset;
3942
3943
  /* Write the fixups and update fields in subspace headers which
3944
     relate to the fixup stream.  */
3945
161
  if (! som_write_fixups (abfd, current_offset, &total_reloc_size))
3946
34
    return false;
3947
3948
  /* Record the total size of the fixup stream in the file header.  */
3949
127
  obj_som_file_hdr (abfd)->fixup_request_total = total_reloc_size;
3950
3951
  /* Done.  Store the total size of the SOM.  */
3952
127
  obj_som_file_hdr (abfd)->som_length = current_offset + total_reloc_size;
3953
3954
  /* Now that the symbol table information is complete, build and
3955
     write the symbol table.  */
3956
127
  if (! som_build_and_write_symbol_table (abfd))
3957
0
    return false;
3958
3959
  /* Subspaces are written first so that we can set up information
3960
     about them in their containing spaces as the subspace is written.  */
3961
3962
  /* Seek to the start of the subspace dictionary records.  */
3963
127
  location = obj_som_file_hdr (abfd)->subspace_location;
3964
127
  if (bfd_seek (abfd, location, SEEK_SET) != 0)
3965
0
    return false;
3966
3967
127
  section = abfd->sections;
3968
  /* Now for each loadable space write out records for its subspaces.  */
3969
215
  for (i = 0; i < num_spaces; i++)
3970
88
    {
3971
88
      asection *subsection;
3972
3973
      /* Find a space.  */
3974
101
      while (!som_is_space (section))
3975
13
  section = section->next;
3976
3977
      /* Now look for all its subspaces.  */
3978
88
      for (subsection = abfd->sections;
3979
378
     subsection != NULL;
3980
290
     subsection = subsection->next)
3981
290
  {
3982
290
    struct som_external_subspace_dictionary_record ext_subspace_dict;
3983
3984
    /* Skip any section which does not correspond to a space
3985
       or subspace.  Or does not have SEC_ALLOC set (and therefore
3986
       has no real bits on the disk).  */
3987
290
    if (!som_is_subspace (subsection)
3988
56
        || !som_is_container (section, subsection)
3989
21
        || (subsection->flags & SEC_ALLOC) == 0)
3990
287
      continue;
3991
3992
    /* If this is the first subspace for this space, then save
3993
       the index of the subspace in its containing space.  Also
3994
       set "is_loadable" in the containing space.  */
3995
3996
3
    if (som_section_data (section)->space_dict->subspace_quantity == 0)
3997
3
      {
3998
3
        som_section_data (section)->space_dict->is_loadable = 1;
3999
3
        som_section_data (section)->space_dict->subspace_index
4000
3
    = subspace_index;
4001
3
      }
4002
4003
    /* Increment the number of subspaces seen and the number of
4004
       subspaces contained within the current space.  */
4005
3
    subspace_index++;
4006
3
    som_section_data (section)->space_dict->subspace_quantity++;
4007
4008
    /* Mark the index of the current space within the subspace's
4009
       dictionary record.  */
4010
3
    som_section_data (subsection)->subspace_dict->space_index = i;
4011
4012
    /* Dump the current subspace header.  */
4013
3
    som_swap_subspace_dictionary_record_out
4014
3
      (som_section_data (subsection)->subspace_dict, &ext_subspace_dict);
4015
3
    amt = sizeof (struct som_subspace_dictionary_record);
4016
3
    if (bfd_write (&ext_subspace_dict, amt, abfd) != amt)
4017
0
      return false;
4018
3
  }
4019
      /* Goto the next section.  */
4020
88
      section = section->next;
4021
88
    }
4022
4023
  /* Now repeat the process for unloadable subspaces.  */
4024
127
  section = abfd->sections;
4025
  /* Now for each space write out records for its subspaces.  */
4026
215
  for (i = 0; i < num_spaces; i++)
4027
88
    {
4028
88
      asection *subsection;
4029
4030
      /* Find a space.  */
4031
101
      while (!som_is_space (section))
4032
13
  section = section->next;
4033
4034
      /* Now look for all its subspaces.  */
4035
88
      for (subsection = abfd->sections;
4036
378
     subsection != NULL;
4037
290
     subsection = subsection->next)
4038
290
  {
4039
290
    struct som_external_subspace_dictionary_record ext_subspace_dict;
4040
4041
    /* Skip any section which does not correspond to a space or
4042
       subspace, or which SEC_ALLOC set (and therefore handled
4043
       in the loadable spaces/subspaces code above).  */
4044
4045
290
    if (!som_is_subspace (subsection)
4046
56
        || !som_is_container (section, subsection)
4047
21
        || (subsection->flags & SEC_ALLOC) != 0)
4048
272
      continue;
4049
4050
    /* If this is the first subspace for this space, then save
4051
       the index of the subspace in its containing space.  Clear
4052
       "is_loadable".  */
4053
4054
18
    if (som_section_data (section)->space_dict->subspace_quantity == 0)
4055
17
      {
4056
17
        som_section_data (section)->space_dict->is_loadable = 0;
4057
17
        som_section_data (section)->space_dict->subspace_index
4058
17
    = subspace_index;
4059
17
      }
4060
4061
    /* Increment the number of subspaces seen and the number of
4062
       subspaces contained within the current space.  */
4063
18
    som_section_data (section)->space_dict->subspace_quantity++;
4064
18
    subspace_index++;
4065
4066
    /* Mark the index of the current space within the subspace's
4067
       dictionary record.  */
4068
18
    som_section_data (subsection)->subspace_dict->space_index = i;
4069
4070
    /* Dump this subspace header.  */
4071
18
    som_swap_subspace_dictionary_record_out
4072
18
      (som_section_data (subsection)->subspace_dict, &ext_subspace_dict);
4073
18
    amt = sizeof (struct som_subspace_dictionary_record);
4074
18
    if (bfd_write (&ext_subspace_dict, amt, abfd) != amt)
4075
0
      return false;
4076
18
  }
4077
      /* Goto the next section.  */
4078
88
      section = section->next;
4079
88
    }
4080
4081
  /* All the subspace dictionary records are written, and all the
4082
     fields are set up in the space dictionary records.
4083
4084
     Seek to the right location and start writing the space
4085
     dictionary records.  */
4086
127
  location = obj_som_file_hdr (abfd)->space_location;
4087
127
  if (bfd_seek (abfd, location, SEEK_SET) != 0)
4088
0
    return false;
4089
4090
127
  section = abfd->sections;
4091
215
  for (i = 0; i < num_spaces; i++)
4092
88
    {
4093
88
      struct som_external_space_dictionary_record ext_space_dict;
4094
4095
      /* Find a space.  */
4096
101
      while (!som_is_space (section))
4097
13
  section = section->next;
4098
4099
      /* Dump its header.  */
4100
88
      som_swap_space_dictionary_out (som_section_data (section)->space_dict,
4101
88
             &ext_space_dict);
4102
88
      amt = sizeof (struct som_external_space_dictionary_record);
4103
88
      if (bfd_write (&ext_space_dict, amt, abfd) != amt)
4104
0
  return false;
4105
4106
      /* Goto the next section.  */
4107
88
      section = section->next;
4108
88
    }
4109
4110
  /* Write the compilation unit record if there is one.  */
4111
127
  if (obj_som_compilation_unit (abfd))
4112
0
    {
4113
0
      struct som_external_compilation_unit ext_comp_unit;
4114
4115
0
      location = obj_som_file_hdr (abfd)->compiler_location;
4116
0
      if (bfd_seek (abfd, location, SEEK_SET) != 0)
4117
0
  return false;
4118
4119
0
      som_swap_compilation_unit_out
4120
0
  (obj_som_compilation_unit (abfd), &ext_comp_unit);
4121
4122
0
      amt = sizeof (struct som_external_compilation_unit);
4123
0
      if (bfd_write (&ext_comp_unit, amt, abfd) != amt)
4124
0
  return false;
4125
0
    }
4126
4127
  /* Setting of the system_id has to happen very late now that copying of
4128
     BFD private data happens *after* section contents are set.  */
4129
127
  if ((abfd->flags & (EXEC_P | DYNAMIC)) && obj_som_exec_data (abfd))
4130
112
    obj_som_file_hdr (abfd)->system_id = obj_som_exec_data (abfd)->system_id;
4131
15
  else if (bfd_get_mach (abfd) == pa20)
4132
0
    obj_som_file_hdr (abfd)->system_id = CPU_PA_RISC2_0;
4133
15
  else if (bfd_get_mach (abfd) == pa11)
4134
0
    obj_som_file_hdr (abfd)->system_id = CPU_PA_RISC1_1;
4135
15
  else
4136
15
    obj_som_file_hdr (abfd)->system_id = CPU_PA_RISC1_0;
4137
4138
  /* Swap and compute the checksum for the file header just before writing
4139
     the header to disk.  */
4140
127
  som_swap_header_out (obj_som_file_hdr (abfd), &ext_header);
4141
127
  bfd_putb32 (som_compute_checksum (&ext_header), ext_header.checksum);
4142
4143
  /* Only thing left to do is write out the file header.  It is always
4144
     at location zero.  Seek there and write it.  */
4145
127
  if (bfd_seek (abfd, 0, SEEK_SET) != 0)
4146
0
    return false;
4147
127
  amt = sizeof (struct som_external_header);
4148
127
  if (bfd_write (&ext_header, amt, abfd) != amt)
4149
0
    return false;
4150
4151
  /* Now write the exec header.  */
4152
127
  if (abfd->flags & (EXEC_P | DYNAMIC))
4153
112
    {
4154
112
      long tmp, som_length;
4155
112
      struct som_exec_auxhdr *exec_header;
4156
112
      struct som_external_exec_auxhdr ext_exec_header;
4157
4158
112
      exec_header = obj_som_exec_hdr (abfd);
4159
112
      exec_header->exec_entry = bfd_get_start_address (abfd);
4160
112
      if (obj_som_exec_data (abfd))
4161
112
  exec_header->exec_flags = obj_som_exec_data (abfd)->exec_flags;
4162
4163
      /* Oh joys.  Ram some of the BSS data into the DATA section
4164
   to be compatible with how the hp linker makes objects
4165
   (saves memory space).  */
4166
112
      tmp = exec_header->exec_dsize;
4167
112
      tmp = SOM_ALIGN (tmp, PA_PAGESIZE);
4168
112
      exec_header->exec_bsize -= (tmp - exec_header->exec_dsize);
4169
112
      if (exec_header->exec_bsize < 0)
4170
0
  exec_header->exec_bsize = 0;
4171
112
      exec_header->exec_dsize = tmp;
4172
4173
      /* Now perform some sanity checks.  The idea is to catch bogons now and
4174
   inform the user, instead of silently generating a bogus file.  */
4175
112
      som_length = obj_som_file_hdr (abfd)->som_length;
4176
112
      if (exec_header->exec_tfile + exec_header->exec_tsize > som_length
4177
112
    || exec_header->exec_dfile + exec_header->exec_dsize > som_length)
4178
0
  {
4179
0
    bfd_set_error (bfd_error_bad_value);
4180
0
    return false;
4181
0
  }
4182
4183
112
      som_swap_exec_auxhdr_out (exec_header, &ext_exec_header);
4184
4185
112
      if (bfd_seek (abfd, obj_som_file_hdr (abfd)->aux_header_location,
4186
112
        SEEK_SET) != 0)
4187
0
  return false;
4188
4189
112
      amt = sizeof (ext_exec_header);
4190
112
      if (bfd_write (&ext_exec_header, amt, abfd) != amt)
4191
0
  return false;
4192
112
    }
4193
127
  return true;
4194
127
}
4195
4196
/* Compute and return the checksum for a SOM file header.  */
4197
4198
static uint32_t
4199
som_compute_checksum (struct som_external_header *hdr)
4200
127
{
4201
127
  size_t count, i;
4202
127
  uint32_t checksum;
4203
127
  uint32_t *buffer = (uint32_t *) hdr;
4204
4205
127
  checksum = 0;
4206
127
  count = sizeof (*hdr) / sizeof (*buffer);
4207
4.19k
  for (i = 0; i < count; i++)
4208
4.06k
    checksum ^= *(buffer + i);
4209
4210
127
  return checksum;
4211
127
}
4212
4213
static void
4214
som_bfd_derive_misc_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
4215
         asymbol *sym,
4216
         struct som_misc_symbol_info *info)
4217
186
{
4218
  /* Initialize.  */
4219
186
  memset (info, 0, sizeof (struct som_misc_symbol_info));
4220
4221
  /* The HP SOM linker requires detailed type information about
4222
     all symbols (including undefined symbols!).  Unfortunately,
4223
     the type specified in an import/export statement does not
4224
     always match what the linker wants.  Severe braindamage.  */
4225
4226
  /* Section symbols will not have a SOM symbol type assigned to
4227
     them yet.  Assign all section symbols type ST_DATA.  */
4228
186
  if (sym->flags & BSF_SECTION_SYM)
4229
0
    info->symbol_type = ST_DATA;
4230
186
  else
4231
186
    {
4232
      /* For BFD style common, the linker will choke unless we set the
4233
   type and scope to ST_STORAGE and SS_UNSAT, respectively.  */
4234
186
      if (bfd_is_com_section (sym->section))
4235
11
  {
4236
11
    info->symbol_type = ST_STORAGE;
4237
11
    info->symbol_scope = SS_UNSAT;
4238
11
  }
4239
4240
      /* It is possible to have a symbol without an associated
4241
   type.  This happens if the user imported the symbol
4242
   without a type and the symbol was never defined
4243
   locally.  If BSF_FUNCTION is set for this symbol, then
4244
   assign it type ST_CODE (the HP linker requires undefined
4245
   external functions to have type ST_CODE rather than ST_ENTRY).  */
4246
175
      else if ((som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN
4247
40
    || som_symbol_data (sym)->som_type == SYMBOL_TYPE_CODE)
4248
136
         && bfd_is_und_section (sym->section)
4249
122
         && sym->flags & BSF_FUNCTION)
4250
2
  info->symbol_type = ST_CODE;
4251
4252
      /* Handle function symbols which were defined in this file.
4253
   They should have type ST_ENTRY.  Also retrieve the argument
4254
   relocation bits from the SOM backend information.  */
4255
173
      else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_ENTRY
4256
170
         || (som_symbol_data (sym)->som_type == SYMBOL_TYPE_CODE
4257
1
       && (sym->flags & BSF_FUNCTION))
4258
170
         || (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN
4259
133
       && (sym->flags & BSF_FUNCTION)))
4260
3
  {
4261
3
    info->symbol_type = ST_ENTRY;
4262
3
    info->arg_reloc = som_symbol_data (sym)->tc_data.ap.hppa_arg_reloc;
4263
3
    info->priv_level= som_symbol_data (sym)->tc_data.ap.hppa_priv_level;
4264
3
  }
4265
4266
      /* For unknown symbols set the symbol's type based on the symbol's
4267
   section (ST_DATA for DATA sections, ST_CODE for CODE sections).  */
4268
170
      else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN)
4269
133
  {
4270
133
    if (bfd_is_abs_section (sym->section))
4271
14
      info->symbol_type = ST_ABSOLUTE;
4272
119
    else if (sym->section->flags & SEC_CODE)
4273
0
      info->symbol_type = ST_CODE;
4274
119
    else
4275
119
      info->symbol_type = ST_DATA;
4276
133
  }
4277
4278
      /* From now on it's a very simple mapping.  */
4279
37
      else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_ABSOLUTE)
4280
2
  info->symbol_type = ST_ABSOLUTE;
4281
35
      else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_CODE)
4282
1
  info->symbol_type = ST_CODE;
4283
34
      else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_DATA)
4284
6
  info->symbol_type = ST_DATA;
4285
28
      else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_MILLICODE)
4286
7
  info->symbol_type = ST_MILLICODE;
4287
21
      else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_PLABEL)
4288
1
  info->symbol_type = ST_PLABEL;
4289
20
      else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_PRI_PROG)
4290
1
  info->symbol_type = ST_PRI_PROG;
4291
19
      else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_SEC_PROG)
4292
19
  info->symbol_type = ST_SEC_PROG;
4293
186
    }
4294
4295
  /* Now handle the symbol's scope.  Exported data which is not
4296
     in the common section has scope SS_UNIVERSAL.  Note scope
4297
     of common symbols was handled earlier!  */
4298
186
  if (bfd_is_com_section (sym->section))
4299
11
    ;
4300
175
  else if (bfd_is_und_section (sym->section))
4301
143
    info->symbol_scope = SS_UNSAT;
4302
32
  else if (sym->flags & (BSF_EXPORT | BSF_WEAK))
4303
19
    info->symbol_scope = SS_UNIVERSAL;
4304
  /* Anything else which is not in the common section has scope
4305
     SS_LOCAL.  */
4306
13
  else
4307
13
    info->symbol_scope = SS_LOCAL;
4308
4309
  /* Now set the symbol_info field.  It has no real meaning
4310
     for undefined or common symbols, but the HP linker will
4311
     choke if it's not set to some "reasonable" value.  We
4312
     use zero as a reasonable value.  */
4313
186
  if (bfd_is_com_section (sym->section)
4314
175
      || bfd_is_und_section (sym->section)
4315
32
      || bfd_is_abs_section (sym->section))
4316
186
    info->symbol_info = 0;
4317
  /* For all other symbols, the symbol_info field contains the
4318
     subspace index of the space this symbol is contained in.  */
4319
0
  else
4320
0
    info->symbol_info = sym->section->target_index;
4321
4322
  /* Set the symbol's value.  */
4323
186
  info->symbol_value = sym->value + sym->section->vma;
4324
4325
  /* The secondary_def field is for "weak" symbols.  */
4326
186
  if (sym->flags & BSF_WEAK)
4327
24
    info->secondary_def = true;
4328
162
  else
4329
162
    info->secondary_def = false;
4330
4331
  /* The is_comdat, is_common and dup_common fields provide various
4332
     flavors of common.
4333
4334
     For data symbols, setting IS_COMMON provides Fortran style common
4335
     (duplicate definitions and overlapped initialization).  Setting both
4336
     IS_COMMON and DUP_COMMON provides Cobol style common (duplicate
4337
     definitions as long as they are all the same length).  In a shared
4338
     link data symbols retain their IS_COMMON and DUP_COMMON flags.
4339
     An IS_COMDAT data symbol is similar to a IS_COMMON | DUP_COMMON
4340
     symbol except in that it loses its IS_COMDAT flag in a shared link.
4341
4342
     For code symbols, IS_COMDAT and DUP_COMMON have effect.  Universal
4343
     DUP_COMMON code symbols are not exported from shared libraries.
4344
     IS_COMDAT symbols are exported but they lose their IS_COMDAT flag.
4345
4346
     We take a simplified approach to setting the is_comdat, is_common
4347
     and dup_common flags in symbols based on the flag settings of their
4348
     subspace.  This avoids having to add directives like `.comdat' but
4349
     the linker behavior is probably undefined if there is more than one
4350
     universal symbol (comdat key sysmbol) in a subspace.
4351
4352
     The behavior of these flags is not well documentmented, so there
4353
     may be bugs and some surprising interactions with other flags.  */
4354
186
  if (sym->section->owner != NULL
4355
0
      && sym->section->owner->xvec->flavour == bfd_target_som_flavour
4356
0
      && som_section_data (sym->section)
4357
0
      && som_section_data (sym->section)->subspace_dict
4358
0
      && info->symbol_scope == SS_UNIVERSAL
4359
0
      && (info->symbol_type == ST_ENTRY
4360
0
    || info->symbol_type == ST_CODE
4361
0
    || info->symbol_type == ST_DATA))
4362
0
    {
4363
0
      info->is_comdat
4364
0
  = som_section_data (sym->section)->subspace_dict->is_comdat;
4365
0
      info->is_common
4366
0
  = som_section_data (sym->section)->subspace_dict->is_common;
4367
0
      info->dup_common
4368
0
  = som_section_data (sym->section)->subspace_dict->dup_common;
4369
0
    }
4370
186
}
4371
4372
/* Build and write, in one big chunk, the entire symbol table for
4373
   this BFD.  */
4374
4375
static bool
4376
som_build_and_write_symbol_table (bfd *abfd)
4377
127
{
4378
127
  unsigned int num_syms = bfd_get_symcount (abfd);
4379
127
  file_ptr symtab_location = obj_som_file_hdr (abfd)->symbol_location;
4380
127
  asymbol **bfd_syms = obj_som_sorted_syms (abfd);
4381
127
  struct som_external_symbol_dictionary_record *som_symtab = NULL;
4382
127
  unsigned int i;
4383
127
  bfd_size_type symtab_size;
4384
127
  size_t amt;
4385
4386
  /* Compute total symbol table size and allocate a chunk of memory
4387
     to hold the symbol table as we build it.  */
4388
127
  if (_bfd_mul_overflow (num_syms,
4389
127
       sizeof (struct som_external_symbol_dictionary_record),
4390
127
       &amt))
4391
0
    {
4392
0
      bfd_set_error (bfd_error_no_memory);
4393
0
      return false;
4394
0
    }
4395
127
  som_symtab = bfd_zmalloc (amt);
4396
127
  if (som_symtab == NULL && num_syms != 0)
4397
0
    goto error_return;
4398
4399
  /* Walk over each symbol.  */
4400
313
  for (i = 0; i < num_syms; i++)
4401
186
    {
4402
186
      struct som_misc_symbol_info info;
4403
186
      unsigned int flags;
4404
4405
      /* This is really an index into the symbol strings table.
4406
   By the time we get here, the index has already been
4407
   computed and stored into the name field in the BFD symbol.  */
4408
186
      bfd_putb32 (som_symbol_data (bfd_syms[i])->stringtab_offset,
4409
186
      som_symtab[i].name);
4410
4411
      /* Derive SOM information from the BFD symbol.  */
4412
186
      som_bfd_derive_misc_symbol_info (abfd, bfd_syms[i], &info);
4413
4414
      /* Now use it.  */
4415
186
      flags = (info.symbol_type << SOM_SYMBOL_TYPE_SH)
4416
186
  | (info.symbol_scope << SOM_SYMBOL_SCOPE_SH)
4417
186
  | (info.arg_reloc << SOM_SYMBOL_ARG_RELOC_SH)
4418
186
  | (3 << SOM_SYMBOL_XLEAST_SH)
4419
186
  | (info.secondary_def ? SOM_SYMBOL_SECONDARY_DEF : 0)
4420
186
  | (info.is_common ? SOM_SYMBOL_IS_COMMON : 0)
4421
186
  | (info.dup_common ? SOM_SYMBOL_DUP_COMMON : 0);
4422
186
      bfd_putb32 (flags, som_symtab[i].flags);
4423
4424
186
      flags = (info.symbol_info << SOM_SYMBOL_SYMBOL_INFO_SH)
4425
186
  | (info.is_comdat ? SOM_SYMBOL_IS_COMDAT : 0);
4426
186
      bfd_putb32 (flags, som_symtab[i].info);
4427
186
      bfd_putb32 (info.symbol_value | info.priv_level,
4428
186
      som_symtab[i].symbol_value);
4429
186
    }
4430
4431
  /* Everything is ready, seek to the right location and
4432
     scribble out the symbol table.  */
4433
127
  if (bfd_seek (abfd, symtab_location, SEEK_SET) != 0)
4434
0
    goto error_return;
4435
4436
127
  symtab_size = num_syms;
4437
127
  symtab_size *= sizeof (struct som_external_symbol_dictionary_record);
4438
127
  if (bfd_write (som_symtab, symtab_size, abfd) != symtab_size)
4439
0
    goto error_return;
4440
4441
127
  free (som_symtab);
4442
127
  return true;
4443
4444
0
 error_return:
4445
0
  free (som_symtab);
4446
0
  return false;
4447
127
}
4448
4449
/* Write an object in SOM format.  */
4450
4451
static bool
4452
som_write_object_contents (bfd *abfd)
4453
161
{
4454
161
  if (! abfd->output_has_begun)
4455
120
    {
4456
      /* Set up fixed parts of the file, space, and subspace headers.
4457
   Notify the world that output has begun.  */
4458
120
      som_prep_headers (abfd);
4459
120
      abfd->output_has_begun = true;
4460
      /* Start writing the object file.  This include all the string
4461
   tables, fixup streams, and other portions of the object file.  */
4462
120
      som_begin_writing (abfd);
4463
120
    }
4464
4465
161
  return som_finish_writing (abfd);
4466
161
}
4467

4468
/* Read and save the string table associated with the given BFD.  */
4469
4470
static bool
4471
som_slurp_string_table (bfd *abfd)
4472
774
{
4473
774
  char *stringtab;
4474
774
  bfd_size_type amt;
4475
4476
  /* Use the saved version if its available.  */
4477
774
  if (obj_som_stringtab (abfd) != NULL)
4478
0
    return true;
4479
4480
  /* I don't think this can currently happen, and I'm not sure it should
4481
     really be an error, but it's better than getting unpredictable results
4482
     from the host's malloc when passed a size of zero.  */
4483
774
  if (obj_som_stringtab_size (abfd) == 0)
4484
12
    {
4485
12
      bfd_set_error (bfd_error_no_symbols);
4486
12
      return false;
4487
12
    }
4488
4489
  /* Allocate and read in the string table.  */
4490
762
  if (bfd_seek (abfd, obj_som_str_filepos (abfd), SEEK_SET) != 0)
4491
0
    return false;
4492
762
  amt = obj_som_stringtab_size (abfd);
4493
762
  stringtab = (char *) _bfd_malloc_and_read (abfd, amt + 1, amt);
4494
762
  if (stringtab == NULL)
4495
184
    return false;
4496
  /* Make sure that the strings are zero-terminated.  */
4497
578
  stringtab[amt] = 0;
4498
4499
  /* Save our results and return success.  */
4500
578
  obj_som_stringtab (abfd) = stringtab;
4501
578
  return true;
4502
762
}
4503
4504
/* Return the amount of data (in bytes) required to hold the symbol
4505
   table for this object.  */
4506
4507
static long
4508
som_get_symtab_upper_bound (bfd *abfd)
4509
1.16k
{
4510
1.16k
  if (!som_slurp_symbol_table (abfd))
4511
318
    return -1;
4512
4513
850
  return (bfd_get_symcount (abfd) + 1) * sizeof (asymbol *);
4514
1.16k
}
4515
4516
/* Convert from a SOM subspace index to a BFD section.  */
4517
4518
asection *
4519
bfd_section_from_som_symbol
4520
  (bfd *abfd, struct som_external_symbol_dictionary_record *symbol)
4521
743
{
4522
743
  asection *section;
4523
743
  unsigned int flags = bfd_getb32 (symbol->flags);
4524
743
  unsigned int symbol_type = (flags >> SOM_SYMBOL_TYPE_SH) & SOM_SYMBOL_TYPE_MASK;
4525
4526
  /* The meaning of the symbol_info field changes for functions
4527
     within executables.  So only use the quick symbol_info mapping for
4528
     incomplete objects and non-function symbols in executables.  */
4529
743
  if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0
4530
596
      || (symbol_type != ST_ENTRY
4531
458
    && symbol_type != ST_PRI_PROG
4532
437
    && symbol_type != ST_SEC_PROG
4533
421
    && symbol_type != ST_MILLICODE))
4534
553
    {
4535
553
      int idx = (bfd_getb32 (symbol->info) >> SOM_SYMBOL_SYMBOL_INFO_SH)
4536
553
  & SOM_SYMBOL_SYMBOL_INFO_MASK;
4537
4538
1.67k
      for (section = abfd->sections; section != NULL; section = section->next)
4539
1.16k
  if (section->target_index == idx && som_is_subspace (section))
4540
45
    return section;
4541
553
    }
4542
190
  else
4543
190
    {
4544
190
      unsigned int value = bfd_getb32 (symbol->symbol_value);
4545
4546
      /* For executables we will have to use the symbol's address and
4547
   find out what section would contain that address.   Yuk.  */
4548
571
      for (section = abfd->sections; section; section = section->next)
4549
466
  if (value >= section->vma
4550
319
      && value <= section->vma + section->size
4551
151
      && som_is_subspace (section))
4552
85
    return section;
4553
190
    }
4554
4555
  /* Could be a symbol from an external library (such as an OMOS
4556
     shared library).  Don't abort.  */
4557
613
  return bfd_abs_section_ptr;
4558
743
}
4559
4560
/* Read and save the symbol table associated with the given BFD.  */
4561
4562
static unsigned int
4563
som_slurp_symbol_table (bfd *abfd)
4564
2.01k
{
4565
2.01k
  unsigned int symbol_count = bfd_get_symcount (abfd);
4566
2.01k
  size_t symsize = sizeof (struct som_external_symbol_dictionary_record);
4567
2.01k
  char *stringtab;
4568
2.01k
  struct som_external_symbol_dictionary_record *buf = NULL, *bufp, *endbufp;
4569
2.01k
  som_symbol_type *sym, *symbase = NULL;
4570
2.01k
  size_t amt;
4571
4572
  /* Return saved value if it exists.  */
4573
2.01k
  if (obj_som_symtab (abfd) != NULL)
4574
1.09k
    goto successful_return;
4575
4576
  /* Special case.  This is *not* an error.  */
4577
924
  if (symbol_count == 0)
4578
150
    goto successful_return;
4579
4580
774
  if (!som_slurp_string_table (abfd))
4581
196
    goto error_return;
4582
4583
578
  stringtab = obj_som_stringtab (abfd);
4584
4585
  /* Read in the external SOM representation.  */
4586
578
  if (_bfd_mul_overflow (symbol_count, symsize, &amt))
4587
0
    {
4588
0
      bfd_set_error (bfd_error_file_too_big);
4589
0
      goto error_return;
4590
0
    }
4591
578
  if (bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET) != 0)
4592
0
    goto error_return;
4593
578
  buf = (struct som_external_symbol_dictionary_record *)
4594
578
    _bfd_malloc_and_read (abfd, amt, amt);
4595
578
  if (buf == NULL)
4596
10
    goto error_return;
4597
4598
568
  if (_bfd_mul_overflow (symbol_count, sizeof (som_symbol_type), &amt))
4599
0
    {
4600
0
      bfd_set_error (bfd_error_file_too_big);
4601
0
      goto error_return;
4602
0
    }
4603
568
  symbase = bfd_zmalloc (amt);
4604
568
  if (symbase == NULL)
4605
0
    goto error_return;
4606
4607
  /* Iterate over all the symbols and internalize them.  */
4608
568
  endbufp = buf + symbol_count;
4609
4.23k
  for (bufp = buf, sym = symbase; bufp < endbufp; ++bufp)
4610
3.77k
    {
4611
3.77k
      unsigned int flags = bfd_getb32 (bufp->flags);
4612
3.77k
      unsigned int symbol_type =
4613
3.77k
  (flags >> SOM_SYMBOL_TYPE_SH) & SOM_SYMBOL_TYPE_MASK;
4614
3.77k
      unsigned int symbol_scope =
4615
3.77k
  (flags >> SOM_SYMBOL_SCOPE_SH) & SOM_SYMBOL_SCOPE_MASK;
4616
3.77k
      bfd_vma offset;
4617
4618
      /* I don't think we care about these.  */
4619
3.77k
      if (symbol_type == ST_SYM_EXT || symbol_type == ST_ARG_EXT)
4620
595
  continue;
4621
4622
      /* Set some private data we care about.  */
4623
3.18k
      if (symbol_type == ST_NULL)
4624
1.70k
  som_symbol_data (sym)->som_type = SYMBOL_TYPE_UNKNOWN;
4625
1.47k
      else if (symbol_type == ST_ABSOLUTE)
4626
39
  som_symbol_data (sym)->som_type = SYMBOL_TYPE_ABSOLUTE;
4627
1.43k
      else if (symbol_type == ST_DATA)
4628
69
  som_symbol_data (sym)->som_type = SYMBOL_TYPE_DATA;
4629
1.36k
      else if (symbol_type == ST_CODE)
4630
44
  som_symbol_data (sym)->som_type = SYMBOL_TYPE_CODE;
4631
1.32k
      else if (symbol_type == ST_PRI_PROG)
4632
47
  som_symbol_data (sym)->som_type = SYMBOL_TYPE_PRI_PROG;
4633
1.27k
      else if (symbol_type == ST_SEC_PROG)
4634
66
  som_symbol_data (sym)->som_type = SYMBOL_TYPE_SEC_PROG;
4635
1.21k
      else if (symbol_type == ST_ENTRY)
4636
184
  som_symbol_data (sym)->som_type = SYMBOL_TYPE_ENTRY;
4637
1.02k
      else if (symbol_type == ST_MILLICODE)
4638
36
  som_symbol_data (sym)->som_type = SYMBOL_TYPE_MILLICODE;
4639
991
      else if (symbol_type == ST_PLABEL)
4640
44
  som_symbol_data (sym)->som_type = SYMBOL_TYPE_PLABEL;
4641
947
      else
4642
947
  som_symbol_data (sym)->som_type = SYMBOL_TYPE_UNKNOWN;
4643
3.18k
      som_symbol_data (sym)->tc_data.ap.hppa_arg_reloc =
4644
3.18k
  (flags >> SOM_SYMBOL_ARG_RELOC_SH) & SOM_SYMBOL_ARG_RELOC_MASK;
4645
4646
      /* Some reasonable defaults.  */
4647
3.18k
      sym->symbol.the_bfd = abfd;
4648
3.18k
      offset = bfd_getb32 (bufp->name);
4649
3.18k
      if (offset < obj_som_stringtab_size (abfd))
4650
3.07k
  sym->symbol.name = offset + stringtab;
4651
112
      else
4652
112
  {
4653
112
    bfd_set_error (bfd_error_bad_value);
4654
112
    goto error_return;
4655
112
  }
4656
3.07k
      sym->symbol.value = bfd_getb32 (bufp->symbol_value);
4657
3.07k
      sym->symbol.section = NULL;
4658
3.07k
      sym->symbol.flags = 0;
4659
4660
3.07k
      switch (symbol_type)
4661
3.07k
  {
4662
182
  case ST_ENTRY:
4663
216
  case ST_MILLICODE:
4664
216
    sym->symbol.flags |= BSF_FUNCTION;
4665
216
    som_symbol_data (sym)->tc_data.ap.hppa_priv_level =
4666
216
      sym->symbol.value & 0x3;
4667
216
    sym->symbol.value &= ~0x3;
4668
216
    break;
4669
4670
35
  case ST_STUB:
4671
78
  case ST_CODE:
4672
124
  case ST_PRI_PROG:
4673
190
  case ST_SEC_PROG:
4674
190
    som_symbol_data (sym)->tc_data.ap.hppa_priv_level =
4675
190
      sym->symbol.value & 0x3;
4676
190
    sym->symbol.value &= ~0x3;
4677
    /* If the symbol's scope is SS_UNSAT, then these are
4678
       undefined function symbols.  */
4679
190
    if (symbol_scope == SS_UNSAT)
4680
92
      sym->symbol.flags |= BSF_FUNCTION;
4681
4682
2.85k
  default:
4683
2.85k
    break;
4684
3.07k
  }
4685
4686
      /* Handle scoping and section information.  */
4687
3.07k
      switch (symbol_scope)
4688
3.07k
  {
4689
  /* symbol_info field is undefined for SS_EXTERNAL and SS_UNSAT symbols,
4690
     so the section associated with this symbol can't be known.  */
4691
92
  case SS_EXTERNAL:
4692
92
    if (symbol_type != ST_STORAGE)
4693
57
      sym->symbol.section = bfd_und_section_ptr;
4694
35
    else
4695
35
      sym->symbol.section = bfd_com_section_ptr;
4696
92
    sym->symbol.flags |= (BSF_EXPORT | BSF_GLOBAL);
4697
92
    break;
4698
4699
1.74k
  case SS_UNSAT:
4700
1.74k
    if (symbol_type != ST_STORAGE)
4701
1.70k
      sym->symbol.section = bfd_und_section_ptr;
4702
42
    else
4703
42
      sym->symbol.section = bfd_com_section_ptr;
4704
1.74k
    break;
4705
4706
255
  case SS_UNIVERSAL:
4707
255
    sym->symbol.flags |= (BSF_EXPORT | BSF_GLOBAL);
4708
255
    sym->symbol.section = bfd_section_from_som_symbol (abfd, bufp);
4709
255
    sym->symbol.value -= sym->symbol.section->vma;
4710
255
    break;
4711
4712
488
  case SS_LOCAL:
4713
488
    sym->symbol.flags |= BSF_LOCAL;
4714
488
    sym->symbol.section = bfd_section_from_som_symbol (abfd, bufp);
4715
488
    sym->symbol.value -= sym->symbol.section->vma;
4716
488
    break;
4717
4718
494
  default:
4719
494
    sym->symbol.section = bfd_und_section_ptr;
4720
494
    break;
4721
3.07k
  }
4722
4723
      /* Check for a weak symbol.  */
4724
3.07k
      if (flags & SOM_SYMBOL_SECONDARY_DEF)
4725
599
  sym->symbol.flags |= BSF_WEAK;
4726
      /* Mark section symbols and symbols used by the debugger.
4727
   Note $START$ is a magic code symbol, NOT a section symbol.  */
4728
3.07k
      if (sym->symbol.name[0] == '$'
4729
458
    && sym->symbol.name[strlen (sym->symbol.name) - 1] == '$'
4730
343
    && !strcmp (sym->symbol.name, sym->symbol.section->name))
4731
0
  sym->symbol.flags |= BSF_SECTION_SYM;
4732
3.07k
      else if (startswith (sym->symbol.name, "L$0\002"))
4733
33
  {
4734
33
    sym->symbol.flags |= BSF_SECTION_SYM;
4735
33
    sym->symbol.name = sym->symbol.section->name;
4736
33
  }
4737
3.03k
      else if (startswith (sym->symbol.name, "L$0\001"))
4738
20
  sym->symbol.flags |= BSF_DEBUGGING;
4739
      /* Note increment at bottom of loop, since we skip some symbols
4740
   we can not include it as part of the for statement.  */
4741
3.07k
      sym++;
4742
3.07k
    }
4743
4744
  /* We modify the symbol count to record the number of BFD symbols we
4745
     created.  */
4746
456
  abfd->symcount = sym - symbase;
4747
4748
  /* Save our results and return success.  */
4749
456
  obj_som_symtab (abfd) = symbase;
4750
1.70k
 successful_return:
4751
1.70k
  free (buf);
4752
1.70k
  return true;
4753
4754
318
 error_return:
4755
318
  free (symbase);
4756
318
  free (buf);
4757
318
  return false;
4758
456
}
4759
4760
/* Canonicalize a SOM symbol table.  Return the number of entries
4761
   in the symbol table.  */
4762
4763
static long
4764
som_canonicalize_symtab (bfd *abfd, asymbol **location)
4765
850
{
4766
850
  int i;
4767
850
  som_symbol_type *symbase;
4768
4769
850
  if (!som_slurp_symbol_table (abfd))
4770
0
    return -1;
4771
4772
850
  i = bfd_get_symcount (abfd);
4773
850
  symbase = obj_som_symtab (abfd);
4774
4775
4.17k
  for (; i > 0; i--, location++, symbase++)
4776
3.32k
    *location = &symbase->symbol;
4777
4778
  /* Final null pointer.  */
4779
850
  *location = 0;
4780
850
  return (bfd_get_symcount (abfd));
4781
850
}
4782
4783
/* Make a SOM symbol.  There is nothing special to do here.  */
4784
4785
static asymbol *
4786
som_make_empty_symbol (bfd *abfd)
4787
43.3k
{
4788
43.3k
  size_t amt = sizeof (som_symbol_type);
4789
43.3k
  som_symbol_type *new_symbol_type = bfd_zalloc (abfd, amt);
4790
4791
43.3k
  if (new_symbol_type == NULL)
4792
0
    return NULL;
4793
43.3k
  new_symbol_type->symbol.the_bfd = abfd;
4794
4795
43.3k
  return &new_symbol_type->symbol;
4796
43.3k
}
4797
4798
/* Print symbol information.  */
4799
4800
static void
4801
som_print_symbol (bfd *abfd,
4802
      void *afile,
4803
      asymbol *symbol,
4804
      bfd_print_symbol_type how)
4805
0
{
4806
0
  FILE *file = (FILE *) afile;
4807
4808
0
  switch (how)
4809
0
    {
4810
0
    case bfd_print_symbol_name:
4811
0
      fprintf (file, "%s", symbol->name);
4812
0
      break;
4813
0
    case bfd_print_symbol_more:
4814
0
      fprintf (file, "som %08" PRIx64 " %x",
4815
0
         (uint64_t) symbol->value, symbol->flags);
4816
0
      break;
4817
0
    case bfd_print_symbol_all:
4818
0
      {
4819
0
  const char *section_name;
4820
4821
0
  section_name = symbol->section ? symbol->section->name : "(*none*)";
4822
0
  bfd_print_symbol_vandf (abfd, (void *) file, symbol);
4823
0
  fprintf (file, " %s\t%s", section_name, symbol->name);
4824
0
  break;
4825
0
      }
4826
0
    }
4827
0
}
4828
4829
static bool
4830
som_bfd_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED,
4831
           const char *name)
4832
0
{
4833
0
  return name[0] == 'L' && name[1] == '$';
4834
0
}
4835
4836
/* Count or process variable-length SOM fixup records.
4837
4838
   To avoid code duplication we use this code both to compute the number
4839
   of relocations requested by a stream, and to internalize the stream.
4840
4841
   When computing the number of relocations requested by a stream the
4842
   variables rptr, section, and symbols have no meaning.
4843
4844
   Return the number of relocations requested by the fixup stream.  When
4845
   not just counting
4846
4847
   This needs at least two or three more passes to get it cleaned up.  */
4848
4849
static unsigned int
4850
som_set_reloc_info (unsigned char *fixup,
4851
        unsigned int end,
4852
        arelent *internal_relocs,
4853
        asection *section,
4854
        asymbol **symbols,
4855
        unsigned int symcount,
4856
        bool just_count)
4857
1.11k
{
4858
1.11k
  unsigned int deallocate_contents = 0;
4859
1.11k
  unsigned char *end_fixups = &fixup[end];
4860
1.11k
  int variables[26], stack[20], count, prev_fixup, *sp, saved_unwind_bits;
4861
1.11k
  arelent *rptr = internal_relocs;
4862
1.11k
  unsigned int offset = 0;
4863
4864
574k
#define var(c)    variables[(c) - 'A']
4865
457k
#define push(v)   (*sp++ = (v))
4866
457k
#define pop()   (*--sp)
4867
1.11k
#define emptystack()  (sp == stack)
4868
4869
1.11k
  som_initialize_reloc_queue (reloc_queue);
4870
1.11k
  memset (variables, 0, sizeof (variables));
4871
1.11k
  memset (stack, 0, sizeof (stack));
4872
1.11k
  count = 0;
4873
1.11k
  prev_fixup = 0;
4874
1.11k
  saved_unwind_bits = 0;
4875
1.11k
  sp = stack;
4876
4877
132k
  while (fixup < end_fixups)
4878
131k
    {
4879
131k
      const char *cp;
4880
131k
      unsigned int op;
4881
131k
      const struct fixup_format *fp;
4882
4883
      /* Save pointer to the start of this fixup.  We'll use
4884
   it later to determine if it is necessary to put this fixup
4885
   on the queue.  */
4886
131k
      unsigned char *save_fixup = fixup;
4887
4888
      /* Get the fixup code and its associated format.  */
4889
131k
      op = *fixup++;
4890
131k
      fp = &som_fixup_formats[op];
4891
4892
      /* Handle a request for a previous fixup.  */
4893
131k
      if (*fp->format == 'P')
4894
12.2k
  {
4895
12.2k
    if (!reloc_queue[fp->D].reloc)
4896
      /* The back-reference doesn't exist.  This is a broken
4897
         object file, likely fuzzed.  Just ignore the fixup.  */
4898
1.45k
      continue;
4899
4900
    /* Get pointer to the beginning of the prev fixup, move
4901
       the repeated fixup to the head of the queue.  */
4902
10.7k
    fixup = reloc_queue[fp->D].reloc;
4903
10.7k
    som_reloc_queue_fix (reloc_queue, fp->D);
4904
10.7k
    prev_fixup = 1;
4905
4906
    /* Get the fixup code and its associated format.  */
4907
10.7k
    op = *fixup++;
4908
10.7k
    fp = &som_fixup_formats[op];
4909
10.7k
  }
4910
4911
      /* If this fixup will be passed to BFD, set some reasonable defaults.  */
4912
130k
      if (! just_count
4913
60.0k
    && som_hppa_howto_table[op].type != R_NO_RELOCATION
4914
28.9k
    && som_hppa_howto_table[op].type != R_DATA_OVERRIDE)
4915
27.8k
  {
4916
27.8k
    rptr->address = offset;
4917
27.8k
    rptr->howto = &som_hppa_howto_table[op];
4918
27.8k
    rptr->addend = 0;
4919
27.8k
    rptr->sym_ptr_ptr = &bfd_abs_section_ptr->symbol;
4920
27.8k
  }
4921
4922
      /* Set default input length to 0.  Get the opcode class index
4923
   into D.  */
4924
130k
      var ('L') = 0;
4925
130k
      var ('D') = fp->D;
4926
130k
      var ('U') = saved_unwind_bits;
4927
4928
      /* Get the opcode format.  */
4929
130k
      cp = fp->format;
4930
4931
      /* Process the format string.  Parsing happens in two phases,
4932
   parse RHS, then assign to LHS.  Repeat until no more
4933
   characters in the format string.  */
4934
282k
      while (*cp)
4935
152k
  {
4936
    /* The variable this pass is going to compute a value for.  */
4937
152k
    unsigned int varname = *cp++;
4938
152k
    const int *subop;
4939
152k
    int c;
4940
4941
    /* Start processing RHS.  Continue until a NULL or '=' is found.  */
4942
152k
    do
4943
457k
      {
4944
457k
        unsigned v;
4945
4946
457k
        c = *cp++;
4947
4948
        /* If this is a variable, push it on the stack.  */
4949
457k
        if (ISUPPER (c))
4950
92.1k
    push (var (c));
4951
4952
        /* If this is a lower case letter, then it represents
4953
     additional data from the fixup stream to be pushed onto
4954
     the stack.  */
4955
365k
        else if (ISLOWER (c))
4956
33.7k
    {
4957
33.7k
      int bits = (c - 'a') * 8;
4958
94.3k
      for (v = 0; c > 'a' && fixup < end_fixups; --c)
4959
60.5k
        v = (v << 8) | *fixup++;
4960
33.7k
      if (varname == 'V')
4961
1.94k
        v = sign_extend (v, bits);
4962
33.7k
      push (v);
4963
33.7k
    }
4964
4965
        /* A decimal constant.  Push it on the stack.  */
4966
331k
        else if (ISDIGIT (c))
4967
179k
    {
4968
179k
      v = c - '0';
4969
179k
      while (ISDIGIT (*cp))
4970
792
        v = (v * 10) + (*cp++ - '0');
4971
179k
      push (v);
4972
179k
    }
4973
152k
        else
4974
    /* An operator.  Pop two values from the stack and
4975
       use them as operands to the given operation.  Push
4976
       the result of the operation back on the stack.  */
4977
152k
    switch (c)
4978
152k
      {
4979
76.8k
      case '+':
4980
76.8k
        v = pop ();
4981
76.8k
        v += pop ();
4982
76.8k
        push (v);
4983
76.8k
        break;
4984
71.2k
      case '*':
4985
71.2k
        v = pop ();
4986
71.2k
        v *= pop ();
4987
71.2k
        push (v);
4988
71.2k
        break;
4989
4.40k
      case '<':
4990
4.40k
        v = pop ();
4991
4.40k
        v = pop () << v;
4992
4.40k
        push (v);
4993
4.40k
        break;
4994
0
      default:
4995
0
        abort ();
4996
152k
      }
4997
457k
      }
4998
457k
    while (*cp && *cp != '=');
4999
5000
    /* Move over the equal operator.  */
5001
152k
    cp++;
5002
5003
    /* Pop the RHS off the stack.  */
5004
152k
    c = pop ();
5005
5006
    /* Perform the assignment.  */
5007
152k
    var (varname) = c;
5008
5009
    /* Handle side effects. and special 'O' stack cases.  */
5010
152k
    switch (varname)
5011
152k
      {
5012
      /* Consume some bytes from the input space.  */
5013
101k
      case 'L':
5014
101k
        offset += c;
5015
101k
        break;
5016
      /* A symbol to use in the relocation.  Make a note
5017
         of this if we are not just counting.  */
5018
29.5k
      case 'S':
5019
29.5k
        if (!just_count && symbols != NULL && (unsigned int) c < symcount)
5020
3.16k
    rptr->sym_ptr_ptr = &symbols[c];
5021
29.5k
        break;
5022
      /* Argument relocation bits for a function call.  */
5023
13.0k
      case 'R':
5024
13.0k
        if (! just_count)
5025
6.21k
    {
5026
6.21k
      unsigned int tmp = var ('R');
5027
6.21k
      rptr->addend = 0;
5028
5029
6.21k
      if ((som_hppa_howto_table[op].type == R_PCREL_CALL
5030
3.84k
           && R_PCREL_CALL + 10 > op)
5031
3.65k
          || (som_hppa_howto_table[op].type == R_ABS_CALL
5032
2.00k
        && R_ABS_CALL + 10 > op))
5033
4.36k
        {
5034
          /* Simple encoding.  */
5035
4.36k
          if (tmp > 4)
5036
1.32k
      {
5037
1.32k
        tmp -= 5;
5038
1.32k
        rptr->addend |= 1;
5039
1.32k
      }
5040
4.36k
          if (tmp == 4)
5041
597
      rptr->addend |= 1 << 8 | 1 << 6 | 1 << 4 | 1 << 2;
5042
3.77k
          else if (tmp == 3)
5043
560
      rptr->addend |= 1 << 8 | 1 << 6 | 1 << 4;
5044
3.21k
          else if (tmp == 2)
5045
736
      rptr->addend |= 1 << 8 | 1 << 6;
5046
2.47k
          else if (tmp == 1)
5047
1.18k
      rptr->addend |= 1 << 8;
5048
4.36k
        }
5049
1.85k
      else
5050
1.85k
        {
5051
1.85k
          unsigned int tmp1, tmp2;
5052
5053
          /* First part is easy -- low order two bits are
5054
       directly copied, then shifted away.  */
5055
1.85k
          rptr->addend = tmp & 0x3;
5056
1.85k
          tmp >>= 2;
5057
5058
          /* Diving the result by 10 gives us the second
5059
       part.  If it is 9, then the first two words
5060
       are a double precision paramater, else it is
5061
       3 * the first arg bits + the 2nd arg bits.  */
5062
1.85k
          tmp1 = tmp / 10;
5063
1.85k
          tmp -= tmp1 * 10;
5064
1.85k
          if (tmp1 == 9)
5065
260
      rptr->addend += (0xe << 6);
5066
1.59k
          else
5067
1.59k
      {
5068
        /* Get the two pieces.  */
5069
1.59k
        tmp2 = tmp1 / 3;
5070
1.59k
        tmp1 -= tmp2 * 3;
5071
        /* Put them in the addend.  */
5072
1.59k
        rptr->addend += (tmp2 << 8) + (tmp1 << 6);
5073
1.59k
      }
5074
5075
          /* What's left is the third part.  It's unpacked
5076
       just like the second.  */
5077
1.85k
          if (tmp == 9)
5078
590
      rptr->addend += (0xe << 2);
5079
1.26k
          else
5080
1.26k
      {
5081
1.26k
        tmp2 = tmp / 3;
5082
1.26k
        tmp -= tmp2 * 3;
5083
1.26k
        rptr->addend += (tmp2 << 4) + (tmp << 2);
5084
1.26k
      }
5085
1.85k
        }
5086
6.21k
      rptr->addend = HPPA_R_ADDEND (rptr->addend, 0);
5087
6.21k
    }
5088
13.0k
        break;
5089
      /* Handle the linker expression stack.  */
5090
538
      case 'O':
5091
538
        switch (op)
5092
538
    {
5093
358
    case R_COMP1:
5094
358
      subop = comp1_opcodes;
5095
358
      break;
5096
120
    case R_COMP2:
5097
120
      subop = comp2_opcodes;
5098
120
      break;
5099
60
    case R_COMP3:
5100
60
      subop = comp3_opcodes;
5101
60
      break;
5102
0
    default:
5103
0
      abort ();
5104
538
    }
5105
10.3k
        while (*subop <= (unsigned char) c)
5106
9.81k
    ++subop;
5107
538
        --subop;
5108
538
        break;
5109
      /* The lower 32unwind bits must be persistent.  */
5110
1.48k
      case 'U':
5111
1.48k
        saved_unwind_bits = var ('U');
5112
1.48k
        break;
5113
5114
6.59k
      default:
5115
6.59k
        break;
5116
152k
      }
5117
152k
  }
5118
5119
      /* If we used a previous fixup, clean up after it.  */
5120
130k
      if (prev_fixup)
5121
10.7k
  {
5122
10.7k
    fixup = save_fixup + 1;
5123
10.7k
    prev_fixup = 0;
5124
10.7k
  }
5125
      /* Queue it.  */
5126
119k
      else if (fixup > save_fixup + 1)
5127
16.4k
  som_reloc_queue_insert (save_fixup, fixup - save_fixup, reloc_queue);
5128
5129
      /* We do not pass R_DATA_OVERRIDE or R_NO_RELOCATION
5130
   fixups to BFD.  */
5131
130k
      if (som_hppa_howto_table[op].type != R_DATA_OVERRIDE
5132
127k
    && som_hppa_howto_table[op].type != R_NO_RELOCATION)
5133
58.9k
  {
5134
    /* Done with a single reloction. Loop back to the top.  */
5135
58.9k
    if (! just_count)
5136
27.8k
      {
5137
27.8k
        if (som_hppa_howto_table[op].type == R_ENTRY)
5138
727
    rptr->addend = var ('T');
5139
27.1k
        else if (som_hppa_howto_table[op].type == R_EXIT)
5140
282
    rptr->addend = var ('U');
5141
26.8k
        else if (som_hppa_howto_table[op].type == R_PCREL_CALL
5142
22.9k
           || som_hppa_howto_table[op].type == R_ABS_CALL)
5143
5.85k
    ;
5144
20.9k
        else if (som_hppa_howto_table[op].type == R_DATA_ONE_SYMBOL)
5145
1.64k
    {
5146
      /* Try what was specified in R_DATA_OVERRIDE first
5147
         (if anything).  Then the hard way using the
5148
         section contents.  */
5149
1.64k
      rptr->addend = var ('V');
5150
5151
1.64k
      if (rptr->addend == 0
5152
1.55k
          && (section->flags & SEC_HAS_CONTENTS) != 0)
5153
1.27k
        {
5154
1.27k
          if (!section->contents)
5155
290
      {
5156
        /* Got to read the damn contents first.  We don't
5157
           bother saving the contents (yet).  Add it one
5158
           day if the need arises.  */
5159
290
        bfd_byte *contents;
5160
290
        if (!bfd_malloc_and_get_section (section->owner,
5161
290
                 section, &contents))
5162
90
          {
5163
90
            free (contents);
5164
90
            return (unsigned) -1;
5165
90
          }
5166
200
        section->contents = contents;
5167
200
        deallocate_contents = 1;
5168
200
      }
5169
1.18k
          if (offset - var ('L') <= section->size
5170
393
        && section->size - (offset - var ('L')) >= 4)
5171
386
      rptr->addend = bfd_get_32 (section->owner,
5172
1.18k
               (section->contents
5173
1.18k
                + offset - var ('L')));
5174
1.18k
        }
5175
1.64k
    }
5176
19.3k
        else
5177
19.3k
    rptr->addend = var ('V');
5178
27.7k
        rptr++;
5179
27.7k
      }
5180
58.8k
    count++;
5181
    /* Now that we've handled a "full" relocation, reset
5182
       some state.  */
5183
58.8k
    memset (variables, 0, sizeof (variables));
5184
58.8k
    memset (stack, 0, sizeof (stack));
5185
58.8k
  }
5186
130k
    }
5187
1.02k
  if (deallocate_contents)
5188
200
    {
5189
200
      free (section->contents);
5190
200
      section->contents = NULL;
5191
200
    }
5192
5193
1.02k
  return count;
5194
5195
1.11k
#undef var
5196
1.11k
#undef push
5197
1.11k
#undef pop
5198
1.11k
#undef emptystack
5199
1.11k
}
5200
5201
/* Read in the relocs (aka fixups in SOM terms) for a section.
5202
5203
   som_get_reloc_upper_bound calls this routine with JUST_COUNT
5204
   set to TRUE to indicate it only needs a count of the number
5205
   of actual relocations.  */
5206
5207
static bool
5208
som_slurp_reloc_table (bfd *abfd,
5209
           asection *section,
5210
           asymbol **symbols,
5211
           bool just_count)
5212
3.18k
{
5213
3.18k
  unsigned char *external_relocs;
5214
3.18k
  unsigned int fixup_stream_size;
5215
3.18k
  arelent *internal_relocs;
5216
3.18k
  unsigned int num_relocs;
5217
3.18k
  size_t amt;
5218
5219
3.18k
  fixup_stream_size = som_section_data (section)->reloc_size;
5220
  /* If there were no relocations, then there is nothing to do.  */
5221
3.18k
  if (section->reloc_count == 0)
5222
47
    return true;
5223
5224
  /* If reloc_count is -1, then the relocation stream has not been
5225
     parsed.  We must do so now to know how many relocations exist.  */
5226
3.13k
  if (section->reloc_count == (unsigned) -1)
5227
2.53k
    {
5228
      /* Read in the external forms.  */
5229
2.53k
      if (bfd_seek (abfd, obj_som_reloc_filepos (abfd) + section->rel_filepos,
5230
2.53k
        SEEK_SET) != 0)
5231
10
  return false;
5232
2.52k
      amt = fixup_stream_size;
5233
2.52k
      external_relocs = _bfd_malloc_and_read (abfd, amt, amt);
5234
2.52k
      if (external_relocs == NULL)
5235
1.96k
  return false;
5236
5237
      /* Let callers know how many relocations found.
5238
   also save the relocation stream as we will
5239
   need it again.  */
5240
560
      section->reloc_count = som_set_reloc_info (external_relocs,
5241
560
             fixup_stream_size,
5242
560
             NULL, NULL, NULL, 0, true);
5243
5244
560
      som_section_data (section)->reloc_stream = external_relocs;
5245
560
    }
5246
5247
  /* If the caller only wanted a count, then return now.  */
5248
1.16k
  if (just_count)
5249
588
    return true;
5250
5251
578
  num_relocs = section->reloc_count;
5252
578
  external_relocs = som_section_data (section)->reloc_stream;
5253
  /* Return saved information about the relocations if it is available.  */
5254
578
  if (section->relocation != NULL)
5255
28
    return true;
5256
5257
550
  if (_bfd_mul_overflow (num_relocs, sizeof (arelent), &amt))
5258
0
    {
5259
0
      bfd_set_error (bfd_error_file_too_big);
5260
0
      return false;
5261
0
    }
5262
550
  internal_relocs = bfd_zalloc (abfd, amt);
5263
550
  if (internal_relocs == NULL)
5264
0
    return false;
5265
5266
  /* Process and internalize the relocations.  */
5267
550
  som_set_reloc_info (external_relocs, fixup_stream_size,
5268
550
          internal_relocs, section, symbols,
5269
550
          bfd_get_symcount (abfd), false);
5270
5271
  /* We're done with the external relocations.  Free them.  */
5272
550
  free (external_relocs);
5273
550
  som_section_data (section)->reloc_stream = NULL;
5274
5275
  /* Save our results and return success.  */
5276
550
  section->relocation = internal_relocs;
5277
550
  return true;
5278
550
}
5279
5280
/* Return the number of bytes required to store the relocation
5281
   information associated with the given section.  */
5282
5283
static long
5284
som_get_reloc_upper_bound (bfd *abfd, sec_ptr asect)
5285
2.59k
{
5286
  /* If section has relocations, then read in the relocation stream
5287
     and parse it to determine how many relocations exist.  */
5288
2.59k
  if (asect->flags & SEC_RELOC)
5289
2.55k
    {
5290
2.55k
      if (! som_slurp_reloc_table (abfd, asect, NULL, true))
5291
1.97k
  return -1;
5292
588
      return (asect->reloc_count + 1) * sizeof (arelent *);
5293
2.55k
    }
5294
5295
  /* There are no relocations.  Return enough space to hold the
5296
     NULL pointer which will be installed if som_canonicalize_reloc
5297
     is called.  */
5298
37
  return sizeof (arelent *);
5299
2.59k
}
5300
5301
/* Convert relocations from SOM (external) form into BFD internal
5302
   form.  Return the number of relocations.  */
5303
5304
static long
5305
som_canonicalize_reloc (bfd *abfd,
5306
      sec_ptr section,
5307
      arelent **relptr,
5308
      asymbol **symbols)
5309
625
{
5310
625
  arelent *tblptr;
5311
625
  int count;
5312
5313
625
  if (! som_slurp_reloc_table (abfd, section, symbols, false))
5314
0
    return -1;
5315
5316
625
  count = section->reloc_count;
5317
625
  tblptr = section->relocation;
5318
5319
36.5k
  while (count--)
5320
35.9k
    *relptr++ = tblptr++;
5321
5322
625
  *relptr = NULL;
5323
625
  return section->reloc_count;
5324
625
}
5325
5326
extern const bfd_target hppa_som_vec;
5327
5328
/* A hook to set up object file dependent section information.  */
5329
5330
static bool
5331
som_new_section_hook (bfd *abfd, asection *newsect)
5332
42.0k
{
5333
42.0k
  size_t amt = sizeof (struct som_section_data_struct);
5334
5335
42.0k
  newsect->used_by_bfd = bfd_zalloc (abfd, amt);
5336
42.0k
  if (!newsect->used_by_bfd)
5337
0
    return false;
5338
5339
42.0k
  newsect->alignment_power = 3;
5340
5341
  /* We allow more than three sections internally.  */
5342
42.0k
  return _bfd_generic_new_section_hook (abfd, newsect);
5343
42.0k
}
5344
5345
/* Copy any private info we understand from the input symbol
5346
   to the output symbol.  */
5347
5348
static bool
5349
som_bfd_copy_private_symbol_data (bfd *ibfd,
5350
          asymbol **isymbol,
5351
          bfd *obfd ATTRIBUTE_UNUSED,
5352
          asymbol **osymbol)
5353
263
{
5354
263
  if (ibfd->xvec->flavour != bfd_target_som_flavour)
5355
0
    {
5356
      /* The som backend makes use of som specific symbol fields
5357
   when outputting symbols.  */
5358
0
      asymbol *osym = som_make_empty_symbol (obfd);
5359
0
      if (osym == NULL)
5360
0
  return false;
5361
0
      memcpy (osym, *isymbol, sizeof (*osym));
5362
0
      osym->the_bfd = obfd;
5363
0
      return true;
5364
0
    }
5365
5366
  /* The only private information we need to copy is the argument relocation
5367
     bits.  */
5368
263
  struct som_symbol *input_symbol = (struct som_symbol *) *isymbol;
5369
263
  struct som_symbol *output_symbol = (struct som_symbol *) *osymbol;
5370
263
  output_symbol->tc_data.ap.hppa_arg_reloc =
5371
263
    input_symbol->tc_data.ap.hppa_arg_reloc;
5372
5373
263
  return true;
5374
263
}
5375
5376
/* Copy any private info we understand from the input section
5377
   to the output section.  */
5378
5379
static bool
5380
som_bfd_copy_private_section_data (bfd *ibfd,
5381
           asection *isection,
5382
           bfd *obfd,
5383
           asection *osection,
5384
           struct bfd_link_info *link_info)
5385
241
{
5386
  /* One day we may try to grok other private data.  */
5387
241
  if (link_info != NULL
5388
241
      || ibfd->xvec->flavour != bfd_target_som_flavour
5389
241
      || (!som_is_space (isection) && !som_is_subspace (isection)))
5390
0
    return true;
5391
5392
241
  size_t amt = sizeof (struct som_copyable_section_data_struct);
5393
241
  som_section_data (osection)->copy_data = bfd_zalloc (obfd, amt);
5394
241
  if (som_section_data (osection)->copy_data == NULL)
5395
0
    return false;
5396
5397
241
  memcpy (som_section_data (osection)->copy_data,
5398
241
    som_section_data (isection)->copy_data,
5399
241
    sizeof (struct som_copyable_section_data_struct));
5400
5401
  /* Reparent if necessary.  */
5402
241
  if (som_section_data (osection)->copy_data->container)
5403
241
    {
5404
241
      if (som_section_data (osection)->copy_data->container->output_section)
5405
241
  som_section_data (osection)->copy_data->container =
5406
241
    som_section_data (osection)->copy_data->container->output_section;
5407
0
      else
5408
0
  {
5409
    /* User has specified a subspace without its containing space.  */
5410
0
    _bfd_error_handler (_("%pB[%pA]: no output section for space %pA"),
5411
0
            obfd, osection,
5412
0
            som_section_data (osection)->copy_data->container);
5413
0
    return false;
5414
0
  }
5415
241
    }
5416
5417
241
  return true;
5418
241
}
5419
5420
/* Copy any private info we understand from the input bfd
5421
   to the output bfd.  */
5422
5423
static bool
5424
som_bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
5425
161
{
5426
  /* One day we may try to grok other private data.  */
5427
161
  if (ibfd->xvec->flavour != bfd_target_som_flavour)
5428
0
    return true;
5429
5430
  /* Allocate some memory to hold the data we need.  */
5431
161
  obj_som_exec_data (obfd) = bfd_zalloc (obfd, (bfd_size_type) sizeof (struct som_exec_data));
5432
161
  if (obj_som_exec_data (obfd) == NULL)
5433
0
    return false;
5434
5435
  /* Now copy the data.  */
5436
161
  memcpy (obj_som_exec_data (obfd), obj_som_exec_data (ibfd),
5437
161
    sizeof (struct som_exec_data));
5438
5439
161
  return true;
5440
161
}
5441
5442
/* Display the SOM header.  */
5443
5444
static bool
5445
som_bfd_print_private_bfd_data (bfd *abfd, void *farg)
5446
230
{
5447
230
  struct som_exec_auxhdr *exec_header;
5448
230
  struct som_aux_id* auxhdr;
5449
230
  FILE *f;
5450
5451
230
  f = (FILE *) farg;
5452
5453
230
  exec_header = obj_som_exec_hdr (abfd);
5454
230
  if (exec_header)
5455
230
    {
5456
230
      fprintf (f, _("\nExec Auxiliary Header\n"));
5457
230
      fprintf (f, "  flags              ");
5458
230
      auxhdr = &exec_header->som_auxhdr;
5459
230
      if (auxhdr->mandatory)
5460
8
  fprintf (f, "mandatory ");
5461
230
      if (auxhdr->copy)
5462
52
  fprintf (f, "copy ");
5463
230
      if (auxhdr->append)
5464
87
  fprintf (f, "append ");
5465
230
      if (auxhdr->ignore)
5466
101
  fprintf (f, "ignore ");
5467
230
      fprintf (f, "\n");
5468
230
      fprintf (f, "  type               %#x\n", auxhdr->type);
5469
230
      fprintf (f, "  length             %#x\n", auxhdr->length);
5470
5471
      /* Note that, depending on the HP-UX version, the following fields can be
5472
   either ints, or longs.  */
5473
5474
230
      fprintf (f, "  text size          %#lx\n", (long) exec_header->exec_tsize);
5475
230
      fprintf (f, "  text memory offset %#lx\n", (long) exec_header->exec_tmem);
5476
230
      fprintf (f, "  text file offset   %#lx\n", (long) exec_header->exec_tfile);
5477
230
      fprintf (f, "  data size          %#lx\n", (long) exec_header->exec_dsize);
5478
230
      fprintf (f, "  data memory offset %#lx\n", (long) exec_header->exec_dmem);
5479
230
      fprintf (f, "  data file offset   %#lx\n", (long) exec_header->exec_dfile);
5480
230
      fprintf (f, "  bss size           %#lx\n", (long) exec_header->exec_bsize);
5481
230
      fprintf (f, "  entry point        %#lx\n", (long) exec_header->exec_entry);
5482
230
      fprintf (f, "  loader flags       %#lx\n", (long) exec_header->exec_flags);
5483
230
      fprintf (f, "  bss initializer    %#lx\n", (long) exec_header->exec_bfill);
5484
230
    }
5485
5486
230
  return true;
5487
230
}
5488
5489
/* Set backend info for sections which can not be described
5490
   in the BFD data structures.  */
5491
5492
bool
5493
bfd_som_set_section_attributes (asection *section,
5494
        int defined,
5495
        int private,
5496
        unsigned int sort_key,
5497
        int spnum)
5498
13.4k
{
5499
  /* Allocate memory to hold the magic information.  */
5500
13.4k
  if (som_section_data (section)->copy_data == NULL)
5501
13.4k
    {
5502
13.4k
      size_t amt = sizeof (struct som_copyable_section_data_struct);
5503
5504
13.4k
      som_section_data (section)->copy_data = bfd_zalloc (section->owner, amt);
5505
13.4k
      if (som_section_data (section)->copy_data == NULL)
5506
0
  return false;
5507
13.4k
    }
5508
13.4k
  som_section_data (section)->copy_data->sort_key = sort_key;
5509
13.4k
  som_section_data (section)->copy_data->is_defined = defined;
5510
13.4k
  som_section_data (section)->copy_data->is_private = private;
5511
13.4k
  som_section_data (section)->copy_data->container = section;
5512
13.4k
  som_section_data (section)->copy_data->space_number = spnum;
5513
13.4k
  return true;
5514
13.4k
}
5515
5516
/* Set backend info for subsections which can not be described
5517
   in the BFD data structures.  */
5518
5519
bool
5520
bfd_som_set_subsection_attributes (asection *section,
5521
           asection *container,
5522
           int access_ctr,
5523
           unsigned int sort_key,
5524
           int quadrant,
5525
           int comdat,
5526
           int common,
5527
           int dup_common)
5528
28.4k
{
5529
  /* Allocate memory to hold the magic information.  */
5530
28.4k
  if (som_section_data (section)->copy_data == NULL)
5531
28.4k
    {
5532
28.4k
      size_t amt = sizeof (struct som_copyable_section_data_struct);
5533
5534
28.4k
      som_section_data (section)->copy_data = bfd_zalloc (section->owner, amt);
5535
28.4k
      if (som_section_data (section)->copy_data == NULL)
5536
0
  return false;
5537
28.4k
    }
5538
28.4k
  som_section_data (section)->copy_data->sort_key = sort_key;
5539
28.4k
  som_section_data (section)->copy_data->access_control_bits = access_ctr;
5540
28.4k
  som_section_data (section)->copy_data->quadrant = quadrant;
5541
28.4k
  som_section_data (section)->copy_data->container = container;
5542
28.4k
  som_section_data (section)->copy_data->is_comdat = comdat;
5543
28.4k
  som_section_data (section)->copy_data->is_common = common;
5544
28.4k
  som_section_data (section)->copy_data->dup_common = dup_common;
5545
28.4k
  return true;
5546
28.4k
}
5547
5548
/* Set the full SOM symbol type.  SOM needs far more symbol information
5549
   than any other object file format I'm aware of.  It is mandatory
5550
   to be able to know if a symbol is an entry point, millicode, data,
5551
   code, absolute, storage request, or procedure label.  If you get
5552
   the symbol type wrong your program will not link.  */
5553
5554
void
5555
bfd_som_set_symbol_type (asymbol *symbol, unsigned int type)
5556
0
{
5557
0
  som_symbol_data (symbol)->som_type = type;
5558
0
}
5559
5560
/* Attach an auxiliary header to the BFD backend so that it may be
5561
   written into the object file.  */
5562
5563
bool
5564
bfd_som_attach_aux_hdr (bfd *abfd, int type, char *string)
5565
0
{
5566
0
  size_t amt;
5567
5568
0
  if (type == VERSION_AUX_ID)
5569
0
    {
5570
0
      size_t len = strlen (string);
5571
0
      int pad = 0;
5572
5573
0
      if (len % 4)
5574
0
  pad = (4 - (len % 4));
5575
0
      amt = sizeof (struct som_string_auxhdr) + len + pad;
5576
0
      obj_som_version_hdr (abfd) = bfd_zalloc (abfd, amt);
5577
0
      if (!obj_som_version_hdr (abfd))
5578
0
  return false;
5579
0
      obj_som_version_hdr (abfd)->header_id.type = VERSION_AUX_ID;
5580
0
      obj_som_version_hdr (abfd)->header_id.length = 4 + len + pad;
5581
0
      obj_som_version_hdr (abfd)->string_length = len;
5582
0
      memcpy (obj_som_version_hdr (abfd)->string, string, len);
5583
0
      memset (obj_som_version_hdr (abfd)->string + len, 0, pad);
5584
0
    }
5585
0
  else if (type == COPYRIGHT_AUX_ID)
5586
0
    {
5587
0
      size_t len = strlen (string);
5588
0
      int pad = 0;
5589
5590
0
      if (len % 4)
5591
0
  pad = (4 - (len % 4));
5592
0
      amt = sizeof (struct som_string_auxhdr) + len + pad;
5593
0
      obj_som_copyright_hdr (abfd) = bfd_zalloc (abfd, amt);
5594
0
      if (!obj_som_copyright_hdr (abfd))
5595
0
  return false;
5596
0
      obj_som_copyright_hdr (abfd)->header_id.type = COPYRIGHT_AUX_ID;
5597
0
      obj_som_copyright_hdr (abfd)->header_id.length = len + pad + 4;
5598
0
      obj_som_copyright_hdr (abfd)->string_length = len;
5599
0
      memcpy (obj_som_copyright_hdr (abfd)->string, string, len);
5600
0
      memset (obj_som_copyright_hdr (abfd)->string + len, 0, pad);
5601
0
    }
5602
0
  return true;
5603
0
}
5604
5605
/* Attach a compilation unit header to the BFD backend so that it may be
5606
   written into the object file.  */
5607
5608
bool
5609
bfd_som_attach_compilation_unit (bfd *abfd,
5610
         const char *name,
5611
         const char *language_name,
5612
         const char *product_id,
5613
         const char *version_id)
5614
0
{
5615
0
  struct som_compilation_unit *n;
5616
5617
0
  n = (struct som_compilation_unit *) bfd_zalloc
5618
0
    (abfd, (bfd_size_type) sizeof (*n));
5619
0
  if (n == NULL)
5620
0
    return false;
5621
5622
0
#define STRDUP(f) \
5623
0
  if (f != NULL) \
5624
0
    { \
5625
0
      n->f.name = bfd_alloc (abfd, (bfd_size_type) strlen (f) + 1); \
5626
0
      if (n->f.name == NULL) \
5627
0
  return false; \
5628
0
      strcpy (n->f.name, f); \
5629
0
    }
5630
5631
0
  STRDUP (name);
5632
0
  STRDUP (language_name);
5633
0
  STRDUP (product_id);
5634
0
  STRDUP (version_id);
5635
5636
0
#undef STRDUP
5637
5638
0
  obj_som_compilation_unit (abfd) = n;
5639
5640
0
  return true;
5641
0
}
5642
5643
static bool
5644
som_get_section_contents (bfd *abfd,
5645
        sec_ptr section,
5646
        void *location,
5647
        file_ptr offset,
5648
        bfd_size_type count)
5649
10.1k
{
5650
10.1k
  if (count == 0 || ((section->flags & SEC_HAS_CONTENTS) == 0))
5651
0
    return true;
5652
10.1k
  if ((bfd_size_type) (offset + count) > section->size
5653
10.1k
      || bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0
5654
10.0k
      || bfd_read (location, count, abfd) != count)
5655
2.22k
    return false; /* On error.  */
5656
7.95k
  return true;
5657
10.1k
}
5658
5659
static bool
5660
som_set_section_contents (bfd *abfd,
5661
        sec_ptr section,
5662
        const void *location,
5663
        file_ptr offset,
5664
        bfd_size_type count)
5665
53
{
5666
53
  if (! abfd->output_has_begun)
5667
41
    {
5668
      /* Set up fixed parts of the file, space, and subspace headers.
5669
   Notify the world that output has begun.  */
5670
41
      som_prep_headers (abfd);
5671
41
      abfd->output_has_begun = true;
5672
      /* Start writing the object file.  This include all the string
5673
   tables, fixup streams, and other portions of the object file.  */
5674
41
      som_begin_writing (abfd);
5675
41
    }
5676
5677
  /* Only write subspaces which have "real" contents (eg. the contents
5678
     are not generated at run time by the OS).  */
5679
53
  if (!som_is_subspace (section)
5680
53
      || ((section->flags & SEC_HAS_CONTENTS) == 0))
5681
0
    return true;
5682
5683
  /* Seek to the proper offset within the object file and write the
5684
     data.  */
5685
53
  offset += som_section_data (section)->subspace_dict->file_loc_init_value;
5686
53
  if (bfd_seek (abfd, offset, SEEK_SET) != 0)
5687
0
    return false;
5688
5689
53
  if (bfd_write (location, count, abfd) != count)
5690
0
    return false;
5691
53
  return true;
5692
53
}
5693
5694
static bool
5695
som_set_arch_mach (bfd *abfd,
5696
       enum bfd_architecture arch,
5697
       unsigned long machine)
5698
253
{
5699
  /* Allow any architecture to be supported by the SOM backend.  */
5700
253
  return bfd_default_set_arch_mach (abfd, arch, machine);
5701
253
}
5702
5703
static bool
5704
som_find_nearest_line (bfd *abfd,
5705
           asymbol **symbols,
5706
           asection *section,
5707
           bfd_vma offset,
5708
           const char **filename_ptr,
5709
           const char **functionname_ptr,
5710
           unsigned int *line_ptr,
5711
           unsigned int *discriminator_ptr)
5712
3.14k
{
5713
3.14k
  bool found;
5714
3.14k
  asymbol *func;
5715
3.14k
  bfd_vma low_func;
5716
3.14k
  asymbol **p;
5717
5718
3.14k
  if (discriminator_ptr)
5719
542
    *discriminator_ptr = 0;
5720
5721
3.14k
  if (! _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset,
5722
3.14k
               & found, filename_ptr,
5723
3.14k
               functionname_ptr, line_ptr,
5724
3.14k
               & somdata (abfd).line_info))
5725
0
    return false;
5726
5727
3.14k
  if (found)
5728
0
    return true;
5729
5730
3.14k
  if (symbols == NULL)
5731
542
    return false;
5732
5733
  /* Fallback: find function name from symbols table.  */
5734
2.60k
  func = NULL;
5735
2.60k
  low_func = 0;
5736
5737
11.4k
  for (p = symbols; *p != NULL; p++)
5738
8.84k
    {
5739
8.84k
      som_symbol_type *q = (som_symbol_type *) *p;
5740
5741
8.84k
      if (q->som_type == SYMBOL_TYPE_ENTRY
5742
1.36k
    && q->symbol.section == section
5743
632
    && q->symbol.value >= low_func
5744
620
    && q->symbol.value <= offset)
5745
340
  {
5746
340
    func = (asymbol *) q;
5747
340
    low_func = q->symbol.value;
5748
340
  }
5749
8.84k
    }
5750
5751
2.60k
  if (func == NULL)
5752
2.26k
    return false;
5753
5754
338
  *filename_ptr = NULL;
5755
338
  *functionname_ptr = bfd_asymbol_name (func);
5756
338
  *line_ptr = 0;
5757
5758
338
  return true;
5759
2.60k
}
5760
5761
static int
5762
som_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
5763
        struct bfd_link_info *info ATTRIBUTE_UNUSED)
5764
0
{
5765
0
  _bfd_error_handler (_("som_sizeof_headers unimplemented"));
5766
0
  abort ();
5767
0
  return 0;
5768
0
}
5769
5770
/* Return the single-character symbol type corresponding to
5771
   SOM section S, or '?' for an unknown SOM section.  */
5772
5773
static char
5774
som_section_type (const char *s)
5775
89
{
5776
89
  const struct section_to_type *t;
5777
5778
1.69k
  for (t = &stt[0]; t->section; t++)
5779
1.60k
    if (!strcmp (s, t->section))
5780
0
      return t->type;
5781
89
  return '?';
5782
89
}
5783
5784
static int
5785
som_decode_symclass (asymbol *symbol)
5786
1.24k
{
5787
1.24k
  char c;
5788
5789
  /* If the symbol did not have a scope specified,
5790
     then it will not have associated section.  */
5791
1.24k
  if (symbol == NULL || symbol->section == NULL)
5792
0
    return '?';
5793
5794
1.24k
  if (bfd_is_com_section (symbol->section))
5795
22
    return 'C';
5796
1.22k
  if (bfd_is_und_section (symbol->section))
5797
860
    {
5798
860
      if (symbol->flags & BSF_WEAK)
5799
206
  {
5800
    /* If weak, determine if it's specifically an object
5801
       or non-object weak.  */
5802
206
    if (symbol->flags & BSF_OBJECT)
5803
0
      return 'v';
5804
206
    else
5805
206
      return 'w';
5806
206
  }
5807
654
      else
5808
654
   return 'U';
5809
860
    }
5810
363
  if (bfd_is_ind_section (symbol->section))
5811
0
    return 'I';
5812
363
  if (symbol->flags & BSF_WEAK)
5813
94
    {
5814
      /* If weak, determine if it's specifically an object
5815
   or non-object weak.  */
5816
94
      if (symbol->flags & BSF_OBJECT)
5817
0
  return 'V';
5818
94
      else
5819
94
  return 'W';
5820
94
    }
5821
269
  if (!(symbol->flags & (BSF_GLOBAL | BSF_LOCAL)))
5822
0
    return '?';
5823
5824
269
  if (bfd_is_abs_section (symbol->section)
5825
95
      || (som_symbol_data (symbol) != NULL
5826
95
    && som_symbol_data (symbol)->som_type == SYMBOL_TYPE_ABSOLUTE))
5827
180
    c = 'a';
5828
89
  else if (symbol->section)
5829
89
    c = som_section_type (symbol->section->name);
5830
0
  else
5831
0
    return '?';
5832
269
  if (symbol->flags & BSF_GLOBAL)
5833
111
    c = TOUPPER (c);
5834
269
  return c;
5835
269
}
5836
5837
/* Return information about SOM symbol SYMBOL in RET.  */
5838
5839
static void
5840
som_get_symbol_info (bfd *ignore_abfd ATTRIBUTE_UNUSED,
5841
         asymbol *symbol,
5842
         symbol_info *ret)
5843
1.24k
{
5844
1.24k
  ret->type = som_decode_symclass (symbol);
5845
1.24k
  if (ret->type != 'U')
5846
591
    ret->value = symbol->value + symbol->section->vma;
5847
654
  else
5848
654
    ret->value = 0;
5849
1.24k
  ret->name = symbol->name;
5850
1.24k
}
5851
5852
/* Count the number of symbols in the archive symbol table.  Necessary
5853
   so that we can allocate space for all the carsyms at once.  */
5854
5855
static bool
5856
som_bfd_count_ar_symbols (bfd *abfd,
5857
        struct som_lst_header *lst_header,
5858
        symindex *count)
5859
601
{
5860
601
  unsigned int i;
5861
601
  unsigned char *hash_table;
5862
601
  size_t amt;
5863
601
  file_ptr lst_filepos;
5864
5865
601
  lst_filepos = bfd_tell (abfd) - sizeof (struct som_external_lst_header);
5866
5867
  /* Read in the hash table.  The hash table is an array of 32-bit
5868
     file offsets which point to the hash chains.  */
5869
601
  if (_bfd_mul_overflow (lst_header->hash_size, 4, &amt))
5870
0
    {
5871
0
      bfd_set_error (bfd_error_file_too_big);
5872
0
      return false;
5873
0
    }
5874
601
  hash_table = _bfd_malloc_and_read (abfd, amt, amt);
5875
601
  if (hash_table == NULL && lst_header->hash_size != 0)
5876
120
    goto error_return;
5877
5878
  /* Don't forget to initialize the counter!  */
5879
481
  *count = 0;
5880
5881
  /* Walk each chain counting the number of symbols found on that particular
5882
     chain.  */
5883
3.67k
  for (i = 0; i < lst_header->hash_size; i++)
5884
3.31k
    {
5885
3.31k
      struct som_external_lst_symbol_record ext_lst_symbol;
5886
3.31k
      unsigned int hash_val = bfd_getb32 (hash_table + 4 * i);
5887
5888
      /* An empty chain has zero as it's file offset.  */
5889
3.31k
      if (hash_val == 0)
5890
2.42k
  continue;
5891
5892
      /* Seek to the first symbol in this hash chain.  */
5893
896
      if (bfd_seek (abfd, lst_filepos + hash_val, SEEK_SET) != 0)
5894
0
  goto error_return;
5895
5896
      /* Read in this symbol and update the counter.  */
5897
896
      amt = sizeof (ext_lst_symbol);
5898
896
      if (bfd_read (&ext_lst_symbol, amt, abfd) != amt)
5899
51
  goto error_return;
5900
5901
845
      (*count)++;
5902
5903
      /* Now iterate through the rest of the symbols on this chain.  */
5904
1.26k
      while (1)
5905
1.26k
  {
5906
1.26k
    unsigned int next_entry = bfd_getb32 (ext_lst_symbol.next_entry);
5907
5908
1.26k
    if (next_entry == 0)
5909
775
      break;
5910
5911
    /* Assume symbols on a chain are in increasing file offset
5912
       order.  Otherwise we can loop here with fuzzed input.  */
5913
489
    if (next_entry < hash_val + sizeof (ext_lst_symbol))
5914
6
      {
5915
6
        bfd_set_error (bfd_error_bad_value);
5916
6
        goto error_return;
5917
6
      }
5918
483
    hash_val = next_entry;
5919
5920
    /* Seek to the next symbol.  */
5921
483
    if (bfd_seek (abfd, lst_filepos + next_entry, SEEK_SET) != 0)
5922
0
      goto error_return;
5923
5924
    /* Read the symbol in and update the counter.  */
5925
483
    amt = sizeof (ext_lst_symbol);
5926
483
    if (bfd_read (&ext_lst_symbol, amt, abfd) != amt)
5927
64
      goto error_return;
5928
5929
419
    (*count)++;
5930
419
  }
5931
845
    }
5932
360
  free (hash_table);
5933
360
  return true;
5934
5935
241
 error_return:
5936
241
  free (hash_table);
5937
241
  return false;
5938
481
}
5939
5940
/* Fill in the canonical archive symbols (SYMS) from the archive described
5941
   by ABFD and LST_HEADER.  */
5942
5943
static bool
5944
som_bfd_fill_in_ar_symbols (bfd *abfd,
5945
          struct som_lst_header *lst_header,
5946
          carsym **syms)
5947
360
{
5948
360
  unsigned int i;
5949
360
  carsym *set = syms[0];
5950
360
  unsigned char *hash_table;
5951
360
  struct som_external_som_entry *som_dict = NULL;
5952
360
  size_t amt;
5953
360
  file_ptr lst_filepos;
5954
360
  unsigned int string_loc;
5955
5956
360
  lst_filepos = bfd_tell (abfd) - sizeof (struct som_external_lst_header);
5957
5958
  /* Read in the hash table.  The has table is an array of 32bit file offsets
5959
     which point to the hash chains.  */
5960
360
  if (_bfd_mul_overflow (lst_header->hash_size, 4, &amt))
5961
0
    {
5962
0
      bfd_set_error (bfd_error_file_too_big);
5963
0
      return false;
5964
0
    }
5965
360
  hash_table = _bfd_malloc_and_read (abfd, amt, amt);
5966
360
  if (hash_table == NULL && lst_header->hash_size != 0)
5967
0
    goto error_return;
5968
5969
  /* Seek to and read in the SOM dictionary.  We will need this to fill
5970
     in the carsym's filepos field.  */
5971
360
  if (bfd_seek (abfd, lst_filepos + lst_header->dir_loc, SEEK_SET) != 0)
5972
0
    goto error_return;
5973
5974
360
  if (_bfd_mul_overflow (lst_header->module_count,
5975
360
       sizeof (struct som_external_som_entry), &amt))
5976
0
    {
5977
0
      bfd_set_error (bfd_error_file_too_big);
5978
0
      goto error_return;
5979
0
    }
5980
360
  som_dict = (struct som_external_som_entry *)
5981
360
    _bfd_malloc_and_read (abfd, amt, amt);
5982
360
  if (som_dict == NULL && lst_header->module_count != 0)
5983
93
    goto error_return;
5984
5985
267
  string_loc = lst_header->string_loc;
5986
5987
  /* Walk each chain filling in the carsyms as we go along.  */
5988
1.76k
  for (i = 0; i < lst_header->hash_size; i++)
5989
1.66k
    {
5990
1.66k
      struct som_external_lst_symbol_record lst_symbol;
5991
1.66k
      unsigned int hash_val;
5992
1.66k
      size_t len;
5993
1.66k
      unsigned char ext_len[4];
5994
1.66k
      char *name;
5995
1.66k
      unsigned int ndx;
5996
5997
      /* An empty chain has zero as it's file offset.  */
5998
1.66k
      hash_val = bfd_getb32 (hash_table + 4 * i);
5999
1.66k
      if (hash_val == 0)
6000
1.29k
  continue;
6001
6002
      /* Seek to and read the first symbol on the chain.  */
6003
373
      if (bfd_seek (abfd, lst_filepos + hash_val, SEEK_SET) != 0)
6004
0
  goto error_return;
6005
6006
373
      amt = sizeof (lst_symbol);
6007
373
      if (bfd_read (&lst_symbol, amt, abfd) != amt)
6008
0
  goto error_return;
6009
6010
      /* Get the name of the symbol, first get the length which is stored
6011
   as a 32bit integer just before the symbol.
6012
6013
   One might ask why we don't just read in the entire string table
6014
   and index into it.  Well, according to the SOM ABI the string
6015
   index can point *anywhere* in the archive to save space, so just
6016
   using the string table would not be safe.  */
6017
373
      if (bfd_seek (abfd, (lst_filepos + string_loc
6018
373
         + bfd_getb32 (lst_symbol.name) - 4), SEEK_SET) != 0)
6019
0
  goto error_return;
6020
6021
373
      if (bfd_read (&ext_len, 4, abfd) != 4)
6022
22
  goto error_return;
6023
351
      len = bfd_getb32 (ext_len);
6024
6025
      /* Allocate space for the name and null terminate it too.  */
6026
351
      if (len == (size_t) -1)
6027
0
  {
6028
0
    bfd_set_error (bfd_error_no_memory);
6029
0
    goto error_return;
6030
0
  }
6031
351
      name = (char *) _bfd_alloc_and_read (abfd, len + 1, len);
6032
351
      if (!name)
6033
64
  goto error_return;
6034
287
      name[len] = 0;
6035
287
      set->name = name;
6036
6037
      /* Fill in the file offset.  Note that the "location" field points
6038
   to the SOM itself, not the ar_hdr in front of it.  */
6039
287
      ndx = bfd_getb32 (lst_symbol.som_index);
6040
287
      if (ndx >= lst_header->module_count)
6041
18
  {
6042
18
    bfd_set_error (bfd_error_bad_value);
6043
18
    goto error_return;
6044
18
  }
6045
269
      set->u.file_offset
6046
269
  = bfd_getb32 (som_dict[ndx].location) - sizeof (struct ar_hdr);
6047
6048
      /* Go to the next symbol.  */
6049
269
      set++;
6050
6051
      /* Iterate through the rest of the chain.  */
6052
384
      while (1)
6053
384
  {
6054
384
    unsigned int next_entry = bfd_getb32 (lst_symbol.next_entry);
6055
6056
384
    if (next_entry == 0)
6057
202
      break;
6058
6059
    /* Seek to the next symbol and read it in.  */
6060
182
    if (bfd_seek (abfd, lst_filepos + next_entry, SEEK_SET) != 0)
6061
0
      goto error_return;
6062
6063
182
    amt = sizeof (lst_symbol);
6064
182
    if (bfd_read (&lst_symbol, amt, abfd) != amt)
6065
0
      goto error_return;
6066
6067
    /* Seek to the name length & string and read them in.  */
6068
182
    if (bfd_seek (abfd, lst_filepos + string_loc
6069
182
      + bfd_getb32 (lst_symbol.name) - 4, SEEK_SET) != 0)
6070
0
      goto error_return;
6071
6072
182
    if (bfd_read (&ext_len, 4, abfd) != 4)
6073
5
      goto error_return;
6074
177
    len = bfd_getb32 (ext_len);
6075
6076
    /* Allocate space for the name and null terminate it too.  */
6077
177
    if (len == (size_t) -1)
6078
0
      {
6079
0
        bfd_set_error (bfd_error_no_memory);
6080
0
        goto error_return;
6081
0
      }
6082
177
    name = (char *) _bfd_alloc_and_read (abfd, len + 1, len);
6083
177
    if (!name)
6084
53
      goto error_return;
6085
124
    name[len] = 0;
6086
124
    set->name = name;
6087
6088
    /* Fill in the file offset.  Note that the "location" field points
6089
       to the SOM itself, not the ar_hdr in front of it.  */
6090
124
    ndx = bfd_getb32 (lst_symbol.som_index);
6091
124
    if (ndx >= lst_header->module_count)
6092
9
      {
6093
9
        bfd_set_error (bfd_error_bad_value);
6094
9
        goto error_return;
6095
9
      }
6096
115
    set->u.file_offset
6097
115
      = bfd_getb32 (som_dict[ndx].location) - sizeof (struct ar_hdr);
6098
6099
    /* Go on to the next symbol.  */
6100
115
    set++;
6101
115
  }
6102
269
    }
6103
  /* If we haven't died by now, then we successfully read the entire
6104
     archive symbol table.  */
6105
96
  free (hash_table);
6106
96
  free (som_dict);
6107
96
  return true;
6108
6109
264
 error_return:
6110
264
  free (hash_table);
6111
264
  free (som_dict);
6112
264
  return false;
6113
267
}
6114
6115
/* Read in the LST from the archive.  */
6116
6117
static bool
6118
som_slurp_armap (bfd *abfd)
6119
48.2k
{
6120
48.2k
  struct som_external_lst_header ext_lst_header;
6121
48.2k
  struct som_lst_header lst_header;
6122
48.2k
  struct ar_hdr ar_header;
6123
48.2k
  unsigned int parsed_size;
6124
48.2k
  struct artdata *ardata = bfd_ardata (abfd);
6125
48.2k
  char nextname[17];
6126
48.2k
  size_t amt = 16;
6127
6128
48.2k
  BFD_ASSERT (!bfd_is_fake_archive (abfd));
6129
6130
48.2k
  int i = bfd_read (nextname, amt, abfd);
6131
6132
  /* Special cases.  */
6133
48.2k
  if (i == 0)
6134
0
    return true;
6135
48.2k
  if (i != 16)
6136
22
    return false;
6137
6138
48.2k
  if (bfd_seek (abfd, -16, SEEK_CUR) != 0)
6139
0
    return false;
6140
6141
  /* For archives without .o files there is no symbol table.  */
6142
48.2k
  if (! startswith (nextname, "/               "))
6143
42.3k
    {
6144
42.3k
      abfd->has_armap = false;
6145
42.3k
      return true;
6146
42.3k
    }
6147
6148
  /* Read in and sanity check the archive header.  */
6149
5.84k
  amt = sizeof (struct ar_hdr);
6150
5.84k
  if (bfd_read (&ar_header, amt, abfd) != amt)
6151
18
    return false;
6152
6153
5.82k
  if (strncmp (ar_header.ar_fmag, ARFMAG, 2))
6154
237
    {
6155
237
      bfd_set_error (bfd_error_malformed_archive);
6156
237
      return false;
6157
237
    }
6158
6159
  /* How big is the archive symbol table entry?  */
6160
5.82k
  errno = 0;
6161
5.58k
  parsed_size = strtol (ar_header.ar_size, NULL, 10);
6162
5.58k
  if (errno != 0)
6163
0
    {
6164
0
      bfd_set_error (bfd_error_malformed_archive);
6165
0
      return false;
6166
0
    }
6167
6168
  /* Save off the file offset of the first real user data.  */
6169
5.58k
  ardata->first_file.file_offset = bfd_tell (abfd) + parsed_size;
6170
6171
  /* Read in the library symbol table.  We'll make heavy use of this
6172
     in just a minute.  */
6173
5.58k
  amt = sizeof (struct som_external_lst_header);
6174
5.58k
  if (bfd_read (&ext_lst_header, amt, abfd) != amt)
6175
181
    return false;
6176
6177
5.40k
  som_swap_lst_header_in (&ext_lst_header, &lst_header);
6178
6179
  /* Sanity check.  */
6180
5.40k
  if (lst_header.a_magic != LIBMAGIC)
6181
4.80k
    {
6182
4.80k
      bfd_set_error (bfd_error_malformed_archive);
6183
4.80k
      return false;
6184
4.80k
    }
6185
6186
  /* Count the number of symbols in the library symbol table.  */
6187
601
  if (! som_bfd_count_ar_symbols (abfd, &lst_header, &ardata->symdef_count))
6188
241
    return false;
6189
6190
  /* Get back to the start of the library symbol table.  */
6191
360
  if (bfd_seek (abfd, (ardata->first_file.file_offset - parsed_size
6192
360
           + sizeof (struct som_external_lst_header)),
6193
360
    SEEK_SET) != 0)
6194
0
    return false;
6195
6196
  /* Initialize the cache and allocate space for the library symbols.  */
6197
360
  ardata->cache = 0;
6198
360
  if (_bfd_mul_overflow (ardata->symdef_count, sizeof (carsym), &amt))
6199
0
    {
6200
0
      bfd_set_error (bfd_error_file_too_big);
6201
0
      return false;
6202
0
    }
6203
360
  ardata->symdefs = bfd_alloc (abfd, amt);
6204
360
  if (!ardata->symdefs)
6205
0
    return false;
6206
6207
  /* Now fill in the canonical archive symbols.  */
6208
360
  if (! som_bfd_fill_in_ar_symbols (abfd, &lst_header, &ardata->symdefs))
6209
264
    return false;
6210
6211
  /* Seek back to the "first" file in the archive.  Note the "first"
6212
     file may be the extended name table.  */
6213
96
  if (bfd_seek (abfd, ardata->first_file.file_offset, SEEK_SET) != 0)
6214
0
    return false;
6215
6216
  /* Notify the generic archive code that we have a symbol map.  */
6217
96
  abfd->has_armap = true;
6218
96
  return true;
6219
96
}
6220
6221
/* Begin preparing to write a SOM library symbol table.
6222
6223
   As part of the prep work we need to determine the number of symbols
6224
   and the size of the associated string section.  */
6225
6226
static bool
6227
som_bfd_prep_for_ar_write (bfd *abfd,
6228
         unsigned int *num_syms,
6229
         unsigned int *stringsize)
6230
4
{
6231
4
  bfd *curr_bfd = abfd->archive_head;
6232
6233
  /* Some initialization.  */
6234
4
  *num_syms = 0;
6235
4
  *stringsize = 0;
6236
6237
  /* Iterate over each BFD within this archive.  */
6238
8
  while (curr_bfd != NULL)
6239
4
    {
6240
4
      unsigned int curr_count, i;
6241
4
      som_symbol_type *sym;
6242
6243
      /* Don't bother for non-SOM objects.  */
6244
4
      if (curr_bfd->format != bfd_object
6245
4
    || curr_bfd->xvec->flavour != bfd_target_som_flavour)
6246
4
  {
6247
4
    curr_bfd = curr_bfd->archive_next;
6248
4
    continue;
6249
4
  }
6250
6251
      /* Make sure the symbol table has been read, then snag a pointer
6252
   to it.  It's a little slimey to grab the symbols via obj_som_symtab,
6253
   but doing so avoids allocating lots of extra memory.  */
6254
0
      if (! som_slurp_symbol_table (curr_bfd))
6255
0
  return false;
6256
6257
0
      sym = obj_som_symtab (curr_bfd);
6258
0
      curr_count = bfd_get_symcount (curr_bfd);
6259
6260
      /* Examine each symbol to determine if it belongs in the
6261
   library symbol table.  */
6262
0
      for (i = 0; i < curr_count; i++, sym++)
6263
0
  {
6264
0
    struct som_misc_symbol_info info;
6265
6266
    /* Derive SOM information from the BFD symbol.  */
6267
0
    som_bfd_derive_misc_symbol_info (curr_bfd, &sym->symbol, &info);
6268
6269
    /* Should we include this symbol?  */
6270
0
    if (info.symbol_type == ST_NULL
6271
0
        || info.symbol_type == ST_SYM_EXT
6272
0
        || info.symbol_type == ST_ARG_EXT)
6273
0
      continue;
6274
6275
    /* Only global symbols and unsatisfied commons.  */
6276
0
    if (info.symbol_scope != SS_UNIVERSAL
6277
0
        && info.symbol_type != ST_STORAGE)
6278
0
      continue;
6279
6280
    /* Do no include undefined symbols.  */
6281
0
    if (bfd_is_und_section (sym->symbol.section))
6282
0
      continue;
6283
6284
    /* Bump the various counters, being careful to honor
6285
       alignment considerations in the string table.  */
6286
0
    (*num_syms)++;
6287
0
    *stringsize += strlen (sym->symbol.name) + 5;
6288
0
    while (*stringsize % 4)
6289
0
      (*stringsize)++;
6290
0
  }
6291
6292
0
      curr_bfd = curr_bfd->archive_next;
6293
0
    }
6294
4
  return true;
6295
4
}
6296
6297
/* Hash a symbol name based on the hashing algorithm presented in the
6298
   SOM ABI.  */
6299
6300
static unsigned int
6301
som_bfd_ar_symbol_hash (asymbol *symbol)
6302
0
{
6303
0
  unsigned int len = strlen (symbol->name);
6304
6305
  /* Names with length 1 are special.  */
6306
0
  if (len == 1)
6307
0
    return 0x1000100 | (symbol->name[0] << 16) | symbol->name[0];
6308
6309
0
  return ((len & 0x7f) << 24) | (symbol->name[1] << 16)
6310
0
    | (symbol->name[len - 2] << 8) | symbol->name[len - 1];
6311
0
}
6312
6313
/* Do the bulk of the work required to write the SOM library
6314
   symbol table.  */
6315
6316
static bool
6317
som_bfd_ar_write_symbol_stuff (bfd *abfd,
6318
             unsigned int nsyms,
6319
             unsigned int string_size,
6320
             struct som_external_lst_header lst,
6321
             unsigned elength)
6322
4
{
6323
4
  char *strings = NULL, *p;
6324
4
  struct som_external_lst_symbol_record *lst_syms = NULL, *curr_lst_sym;
6325
4
  bfd *curr_bfd;
6326
4
  unsigned char *hash_table = NULL;
6327
4
  struct som_external_som_entry *som_dict = NULL;
6328
4
  struct som_external_lst_symbol_record **last_hash_entry = NULL;
6329
4
  unsigned int curr_som_offset, som_index = 0;
6330
4
  size_t amt;
6331
4
  unsigned int module_count;
6332
4
  unsigned int hash_size;
6333
6334
4
  hash_size = bfd_getb32 (lst.hash_size);
6335
4
  if (_bfd_mul_overflow (hash_size, 4, &amt))
6336
0
    {
6337
0
      bfd_set_error (bfd_error_no_memory);
6338
0
      return false;
6339
0
    }
6340
4
  hash_table = bfd_zmalloc (amt);
6341
4
  if (hash_table == NULL && hash_size != 0)
6342
0
    goto error_return;
6343
6344
4
  module_count = bfd_getb32 (lst.module_count);
6345
4
  if (_bfd_mul_overflow (module_count,
6346
4
       sizeof (struct som_external_som_entry), &amt))
6347
0
    {
6348
0
      bfd_set_error (bfd_error_no_memory);
6349
0
      goto error_return;
6350
0
    }
6351
4
  som_dict = bfd_zmalloc (amt);
6352
4
  if (som_dict == NULL && module_count != 0)
6353
0
    goto error_return;
6354
6355
4
  if (_bfd_mul_overflow (hash_size,
6356
4
       sizeof (struct som_external_lst_symbol_record *),
6357
4
       &amt))
6358
0
    {
6359
0
      bfd_set_error (bfd_error_no_memory);
6360
0
      goto error_return;
6361
0
    }
6362
4
  last_hash_entry = bfd_zmalloc (amt);
6363
4
  if (last_hash_entry == NULL && hash_size != 0)
6364
0
    goto error_return;
6365
6366
  /* Symbols have som_index fields, so we have to keep track of the
6367
     index of each SOM in the archive.
6368
6369
     The SOM dictionary has (among other things) the absolute file
6370
     position for the SOM which a particular dictionary entry
6371
     describes.  We have to compute that information as we iterate
6372
     through the SOMs/symbols.  */
6373
4
  som_index = 0;
6374
6375
  /* We add in the size of the archive header twice as the location
6376
     in the SOM dictionary is the actual offset of the SOM, not the
6377
     archive header before the SOM.  */
6378
4
  curr_som_offset = 8 + 2 * sizeof (struct ar_hdr) + bfd_getb32 (lst.file_end);
6379
6380
  /* Make room for the archive header and the contents of the
6381
     extended string table.  Note that elength includes the size
6382
     of the archive header for the extended name table!  */
6383
4
  if (elength)
6384
0
    curr_som_offset += elength;
6385
6386
  /* Make sure we're properly aligned.  */
6387
4
  curr_som_offset = (curr_som_offset + 0x1) & ~0x1;
6388
6389
  /* FIXME should be done with buffers just like everything else...  */
6390
4
  if (_bfd_mul_overflow (nsyms,
6391
4
       sizeof (struct som_external_lst_symbol_record), &amt))
6392
0
    {
6393
0
      bfd_set_error (bfd_error_no_memory);
6394
0
      goto error_return;
6395
0
    }
6396
4
  lst_syms = bfd_malloc (amt);
6397
4
  if (lst_syms == NULL && nsyms != 0)
6398
0
    goto error_return;
6399
4
  strings = bfd_malloc (string_size);
6400
4
  if (strings == NULL && string_size != 0)
6401
0
    goto error_return;
6402
6403
4
  p = strings;
6404
4
  curr_lst_sym = lst_syms;
6405
6406
4
  curr_bfd = abfd->archive_head;
6407
8
  while (curr_bfd != NULL)
6408
4
    {
6409
4
      unsigned int curr_count, i;
6410
4
      som_symbol_type *sym;
6411
6412
      /* Don't bother for non-SOM objects.  */
6413
4
      if (curr_bfd->format != bfd_object
6414
4
    || curr_bfd->xvec->flavour != bfd_target_som_flavour)
6415
4
  {
6416
4
    curr_bfd = curr_bfd->archive_next;
6417
4
    continue;
6418
4
  }
6419
6420
      /* Make sure the symbol table has been read, then snag a pointer
6421
   to it.  It's a little slimey to grab the symbols via obj_som_symtab,
6422
   but doing so avoids allocating lots of extra memory.  */
6423
0
      if (! som_slurp_symbol_table (curr_bfd))
6424
0
  goto error_return;
6425
6426
0
      sym = obj_som_symtab (curr_bfd);
6427
0
      curr_count = bfd_get_symcount (curr_bfd);
6428
6429
0
      for (i = 0; i < curr_count; i++, sym++)
6430
0
  {
6431
0
    struct som_misc_symbol_info info;
6432
0
    struct som_external_lst_symbol_record *last;
6433
0
    unsigned int symbol_pos;
6434
0
    unsigned int slen;
6435
0
    unsigned int symbol_key;
6436
0
    unsigned int flags;
6437
6438
    /* Derive SOM information from the BFD symbol.  */
6439
0
    som_bfd_derive_misc_symbol_info (curr_bfd, &sym->symbol, &info);
6440
6441
    /* Should we include this symbol?  */
6442
0
    if (info.symbol_type == ST_NULL
6443
0
        || info.symbol_type == ST_SYM_EXT
6444
0
        || info.symbol_type == ST_ARG_EXT)
6445
0
      continue;
6446
6447
    /* Only global symbols and unsatisfied commons.  */
6448
0
    if (info.symbol_scope != SS_UNIVERSAL
6449
0
        && info.symbol_type != ST_STORAGE)
6450
0
      continue;
6451
6452
    /* Do no include undefined symbols.  */
6453
0
    if (bfd_is_und_section (sym->symbol.section))
6454
0
      continue;
6455
6456
    /* If this is the first symbol from this SOM, then update
6457
       the SOM dictionary too.  */
6458
0
    if (bfd_getb32 (som_dict[som_index].location) == 0)
6459
0
      {
6460
0
        bfd_putb32 (curr_som_offset, som_dict[som_index].location);
6461
0
        bfd_putb32 (arelt_size (curr_bfd), som_dict[som_index].length);
6462
0
      }
6463
6464
0
    symbol_key = som_bfd_ar_symbol_hash (&sym->symbol);
6465
6466
    /* Fill in the lst symbol record.  */
6467
0
    flags = 0;
6468
0
    if (info.secondary_def)
6469
0
      flags |= LST_SYMBOL_SECONDARY_DEF;
6470
0
    flags |= info.symbol_type << LST_SYMBOL_SYMBOL_TYPE_SH;
6471
0
    flags |= info.symbol_scope << LST_SYMBOL_SYMBOL_SCOPE_SH;
6472
0
    if (bfd_is_com_section (sym->symbol.section))
6473
0
      flags |= LST_SYMBOL_IS_COMMON;
6474
0
    if (info.dup_common)
6475
0
      flags |= LST_SYMBOL_DUP_COMMON;
6476
0
    flags |= 3 << LST_SYMBOL_XLEAST_SH;
6477
0
    flags |= info.arg_reloc << LST_SYMBOL_ARG_RELOC_SH;
6478
0
    bfd_putb32 (flags, curr_lst_sym->flags);
6479
0
    bfd_putb32 (p - strings + 4, curr_lst_sym->name);
6480
0
    bfd_putb32 (0, curr_lst_sym->qualifier_name);
6481
0
    bfd_putb32 (info.symbol_info, curr_lst_sym->symbol_info);
6482
0
    bfd_putb32 (info.symbol_value | info.priv_level,
6483
0
          curr_lst_sym->symbol_value);
6484
0
    bfd_putb32 (0, curr_lst_sym->symbol_descriptor);
6485
0
    curr_lst_sym->reserved = 0;
6486
0
    bfd_putb32 (som_index, curr_lst_sym->som_index);
6487
0
    bfd_putb32 (symbol_key, curr_lst_sym->symbol_key);
6488
0
    bfd_putb32 (0, curr_lst_sym->next_entry);
6489
6490
    /* Insert into the hash table.  */
6491
0
    symbol_pos =
6492
0
      (curr_lst_sym - lst_syms)
6493
0
      * sizeof (struct som_external_lst_symbol_record)
6494
0
      + hash_size * 4
6495
0
      + module_count * sizeof (struct som_external_som_entry)
6496
0
      + sizeof (struct som_external_lst_header);
6497
0
    last = last_hash_entry[symbol_key % hash_size];
6498
0
    if (last != NULL)
6499
0
      {
6500
        /* There is already something at the head of this hash chain,
6501
     so tack this symbol onto the end of the chain.  */
6502
0
        bfd_putb32 (symbol_pos, last->next_entry);
6503
0
      }
6504
0
    else
6505
      /* First entry in this hash chain.  */
6506
0
      bfd_putb32 (symbol_pos, hash_table + 4 * (symbol_key % hash_size));
6507
6508
    /* Keep track of the last symbol we added to this chain so we can
6509
       easily update its next_entry pointer.  */
6510
0
    last_hash_entry[symbol_key % hash_size] = curr_lst_sym;
6511
6512
    /* Update the string table.  */
6513
0
    slen = strlen (sym->symbol.name);
6514
0
    bfd_put_32 (abfd, slen, p);
6515
0
    p += 4;
6516
0
    slen++; /* Nul terminator.  */
6517
0
    memcpy (p, sym->symbol.name, slen);
6518
0
    p += slen;
6519
0
    while (slen % 4)
6520
0
      {
6521
0
        bfd_put_8 (abfd, 0, p);
6522
0
        p++;
6523
0
        slen++;
6524
0
      }
6525
0
    BFD_ASSERT (p <= strings + string_size);
6526
6527
    /* Head to the next symbol.  */
6528
0
    curr_lst_sym++;
6529
0
  }
6530
6531
      /* Keep track of where each SOM will finally reside; then look
6532
   at the next BFD.  */
6533
0
      curr_som_offset += arelt_size (curr_bfd) + sizeof (struct ar_hdr);
6534
6535
      /* A particular object in the archive may have an odd length; the
6536
   linker requires objects begin on an even boundary.  So round
6537
   up the current offset as necessary.  */
6538
0
      curr_som_offset = (curr_som_offset + 0x1) &~ (unsigned) 1;
6539
0
      curr_bfd = curr_bfd->archive_next;
6540
0
      som_index++;
6541
0
    }
6542
6543
  /* Now scribble out the hash table.  */
6544
4
  amt = (size_t) hash_size * 4;
6545
4
  if (bfd_write (hash_table, amt, abfd) != amt)
6546
0
    goto error_return;
6547
6548
  /* Then the SOM dictionary.  */
6549
4
  amt = (size_t) module_count * sizeof (struct som_external_som_entry);
6550
4
  if (bfd_write (som_dict, amt, abfd) != amt)
6551
0
    goto error_return;
6552
6553
  /* The library symbols.  */
6554
4
  amt = (size_t) nsyms * sizeof (struct som_external_lst_symbol_record);
6555
4
  if (bfd_write (lst_syms, amt, abfd) != amt)
6556
0
    goto error_return;
6557
6558
  /* And finally the strings.  */
6559
4
  amt = string_size;
6560
4
  if (bfd_write (strings, amt, abfd) != amt)
6561
0
    goto error_return;
6562
6563
4
  free (hash_table);
6564
4
  free (som_dict);
6565
4
  free (last_hash_entry);
6566
4
  free (lst_syms);
6567
4
  free (strings);
6568
4
  return true;
6569
6570
0
 error_return:
6571
0
  free (hash_table);
6572
0
  free (som_dict);
6573
0
  free (last_hash_entry);
6574
0
  free (lst_syms);
6575
0
  free (strings);
6576
6577
0
  return false;
6578
4
}
6579
6580
/* Write out the LST for the archive.
6581
6582
   You'll never believe this is really how armaps are handled in SOM...  */
6583
6584
static bool
6585
som_write_armap (bfd *abfd,
6586
     unsigned int elength,
6587
     struct orl *map ATTRIBUTE_UNUSED,
6588
     unsigned int orl_count ATTRIBUTE_UNUSED,
6589
     int stridx ATTRIBUTE_UNUSED)
6590
4
{
6591
4
  bfd *curr_bfd;
6592
4
  struct stat statbuf;
6593
4
  unsigned int i, lst_size, nsyms, stringsize;
6594
4
  struct ar_hdr hdr;
6595
4
  struct som_external_lst_header lst;
6596
4
  unsigned char *p;
6597
4
  size_t amt;
6598
4
  unsigned int csum;
6599
4
  unsigned int module_count;
6600
6601
  /* We'll use this for the archive's date and mode later.  */
6602
4
  if (stat (bfd_get_filename (abfd), &statbuf) != 0)
6603
0
    {
6604
0
      bfd_set_error (bfd_error_system_call);
6605
0
      return false;
6606
0
    }
6607
  /* Fudge factor.  */
6608
4
  bfd_ardata (abfd)->armap_timestamp = statbuf.st_mtime + 60;
6609
6610
  /* Account for the lst header first.  */
6611
4
  lst_size = sizeof (struct som_external_lst_header);
6612
6613
  /* Start building the LST header.  */
6614
  /* FIXME:  Do we need to examine each element to determine the
6615
     largest id number?  */
6616
4
  bfd_putb16 (CPU_PA_RISC1_0, &lst.system_id);
6617
4
  bfd_putb16 (LIBMAGIC, &lst.a_magic);
6618
4
  bfd_putb32 (VERSION_ID, &lst.version_id);
6619
4
  bfd_putb32 (0, &lst.file_time.secs);
6620
4
  bfd_putb32 (0, &lst.file_time.nanosecs);
6621
6622
4
  bfd_putb32 (lst_size, &lst.hash_loc);
6623
4
  bfd_putb32 (SOM_LST_HASH_SIZE, &lst.hash_size);
6624
6625
  /* Hash table is a SOM_LST_HASH_SIZE 32bit offsets.  */
6626
4
  lst_size += 4 * SOM_LST_HASH_SIZE;
6627
6628
  /* We need to count the number of SOMs in this archive.  */
6629
4
  curr_bfd = abfd->archive_head;
6630
4
  module_count = 0;
6631
8
  while (curr_bfd != NULL)
6632
4
    {
6633
      /* Only true SOM objects count.  */
6634
4
      if (curr_bfd->format == bfd_object
6635
4
    && curr_bfd->xvec->flavour == bfd_target_som_flavour)
6636
0
  module_count++;
6637
4
      curr_bfd = curr_bfd->archive_next;
6638
4
    }
6639
4
  bfd_putb32 (module_count, &lst.module_count);
6640
4
  bfd_putb32 (module_count, &lst.module_limit);
6641
4
  bfd_putb32 (lst_size, &lst.dir_loc);
6642
4
  lst_size += sizeof (struct som_external_som_entry) * module_count;
6643
6644
  /* We don't support import/export tables, auxiliary headers,
6645
     or free lists yet.  Make the linker work a little harder
6646
     to make our life easier.  */
6647
6648
4
  bfd_putb32 (0, &lst.export_loc);
6649
4
  bfd_putb32 (0, &lst.export_count);
6650
4
  bfd_putb32 (0, &lst.import_loc);
6651
4
  bfd_putb32 (0, &lst.aux_loc);
6652
4
  bfd_putb32 (0, &lst.aux_size);
6653
6654
  /* Count how many symbols we will have on the hash chains and the
6655
     size of the associated string table.  */
6656
4
  if (! som_bfd_prep_for_ar_write (abfd, &nsyms, &stringsize))
6657
0
    return false;
6658
6659
4
  lst_size += sizeof (struct som_external_lst_symbol_record) * nsyms;
6660
6661
  /* For the string table.  One day we might actually use this info
6662
     to avoid small seeks/reads when reading archives.  */
6663
4
  bfd_putb32 (lst_size, &lst.string_loc);
6664
4
  bfd_putb32 (stringsize, &lst.string_size);
6665
4
  lst_size += stringsize;
6666
6667
  /* SOM ABI says this must be zero.  */
6668
4
  bfd_putb32 (0, &lst.free_list);
6669
4
  bfd_putb32 (lst_size, &lst.file_end);
6670
6671
  /* Compute the checksum.  Must happen after the entire lst header
6672
     has filled in.  */
6673
4
  p = (unsigned char *) &lst;
6674
4
  csum = 0;
6675
76
  for (i = 0; i < sizeof (struct som_external_lst_header) - sizeof (int);
6676
72
       i += 4)
6677
72
    csum ^= bfd_getb32 (&p[i]);
6678
4
  bfd_putb32 (csum, &lst.checksum);
6679
6680
4
  sprintf (hdr.ar_name, "/              ");
6681
4
  _bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%-12ld",
6682
4
        bfd_ardata (abfd)->armap_timestamp);
6683
4
  _bfd_ar_spacepad (hdr.ar_uid, sizeof (hdr.ar_uid), "%ld",
6684
4
        statbuf.st_uid);
6685
4
  _bfd_ar_spacepad (hdr.ar_gid, sizeof (hdr.ar_gid), "%ld",
6686
4
        statbuf.st_gid);
6687
4
  _bfd_ar_spacepad (hdr.ar_mode, sizeof (hdr.ar_mode), "%-8o",
6688
4
        (unsigned int)statbuf.st_mode);
6689
4
  _bfd_ar_spacepad (hdr.ar_size, sizeof (hdr.ar_size), "%-10d",
6690
4
        (int) lst_size);
6691
4
  hdr.ar_fmag[0] = '`';
6692
4
  hdr.ar_fmag[1] = '\012';
6693
6694
  /* Turn any nulls into spaces.  */
6695
244
  for (i = 0; i < sizeof (struct ar_hdr); i++)
6696
240
    if (((char *) (&hdr))[i] == '\0')
6697
4
      (((char *) (&hdr))[i]) = ' ';
6698
6699
  /* Scribble out the ar header.  */
6700
4
  amt = sizeof (struct ar_hdr);
6701
4
  if (bfd_write (&hdr, amt, abfd) != amt)
6702
0
    return false;
6703
6704
  /* Now scribble out the lst header.  */
6705
4
  amt = sizeof (struct som_external_lst_header);
6706
4
  if (bfd_write (&lst, amt, abfd) != amt)
6707
0
    return false;
6708
6709
  /* Build and write the armap.  */
6710
4
  if (!som_bfd_ar_write_symbol_stuff (abfd, nsyms, stringsize, lst, elength))
6711
0
    return false;
6712
6713
  /* Done.  */
6714
4
  return true;
6715
4
}
6716
6717
/* Throw away some malloc'd information for this BFD.  */
6718
6719
static bool
6720
som_bfd_free_cached_info (bfd *abfd)
6721
43.0k
{
6722
43.0k
#define FREE(x) do { free (x); x = NULL; } while (0)
6723
43.0k
  if (bfd_get_format (abfd) == bfd_object
6724
1.74k
      && abfd->tdata.som_data != NULL)
6725
1.74k
    {
6726
      /* Free the native string and symbol tables.  */
6727
1.74k
      FREE (obj_som_symtab (abfd));
6728
1.74k
      FREE (obj_som_stringtab (abfd));
6729
1.74k
    }
6730
6731
58.5k
  for (asection *o = abfd->sections; o != NULL; o = o->next)
6732
15.4k
    {
6733
      /* Free the native relocations.  */
6734
15.4k
      o->reloc_count = (unsigned) -1;
6735
15.4k
      FREE (som_section_data (o)->reloc_stream);
6736
      /* Do not free the generic relocations as they are objalloc'ed.  */
6737
15.4k
    }
6738
43.0k
#undef FREE
6739
6740
  /* Do not call _bfd_generic_bfd_free_cached_info here.
6741
     som_write_armap needs to access the bfd objalloc memory.  */
6742
43.0k
  return true;
6743
43.0k
}
6744
6745
/* End of miscellaneous support functions.  */
6746
6747
/* Linker support functions.  */
6748
6749
static bool
6750
som_bfd_link_split_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
6751
0
{
6752
0
  return som_is_subspace (sec) && sec->size > 240000;
6753
0
}
6754
6755
#define som_find_line       _bfd_nosymbols_find_line
6756
#define som_get_symbol_version_string   _bfd_nosymbols_get_symbol_version_string
6757
#define som_close_and_cleanup     _bfd_generic_close_and_cleanup
6758
#define som_read_ar_hdr       _bfd_generic_read_ar_hdr
6759
#define som_write_ar_hdr      _bfd_generic_write_ar_hdr
6760
#define som_openr_next_archived_file    bfd_generic_openr_next_archived_file
6761
#define som_get_elt_at_index      _bfd_generic_get_elt_at_index
6762
#define som_generic_stat_arch_elt   bfd_generic_stat_arch_elt
6763
#define som_truncate_arname     bfd_bsd_truncate_arname
6764
#define som_slurp_extended_name_table   _bfd_slurp_extended_name_table
6765
#define som_construct_extended_name_table _bfd_archive_coff_construct_extended_name_table
6766
#define som_update_armap_timestamp    _bfd_bool_bfd_true
6767
#define som_bfd_is_target_special_symbol        _bfd_bool_bfd_asymbol_false
6768
#define som_get_lineno        _bfd_nosymbols_get_lineno
6769
#define som_bfd_make_debug_symbol   _bfd_nosymbols_bfd_make_debug_symbol
6770
#define som_read_minisymbols      _bfd_generic_read_minisymbols
6771
#define som_minisymbol_to_symbol    _bfd_generic_minisymbol_to_symbol
6772
#define som_bfd_get_relocated_section_contents  bfd_generic_get_relocated_section_contents
6773
#define som_bfd_relax_section     bfd_generic_relax_section
6774
#define som_bfd_link_hash_table_create    _bfd_generic_link_hash_table_create
6775
#define som_bfd_link_add_symbols    _bfd_generic_link_add_symbols
6776
#define som_bfd_link_just_syms      _bfd_generic_link_just_syms
6777
#define som_bfd_copy_link_hash_symbol_type \
6778
  _bfd_generic_copy_link_hash_symbol_type
6779
#define som_bfd_final_link      _bfd_generic_final_link
6780
#define som_bfd_gc_sections     bfd_generic_gc_sections
6781
#define som_bfd_lookup_section_flags    bfd_generic_lookup_section_flags
6782
#define som_bfd_is_group_section    bfd_generic_is_group_section
6783
#define som_bfd_group_name      bfd_generic_group_name
6784
#define som_bfd_discard_group     bfd_generic_discard_group
6785
#define som_section_already_linked    _bfd_generic_section_already_linked
6786
#define som_bfd_define_common_symbol    bfd_generic_define_common_symbol
6787
#define som_bfd_link_hide_symbol    _bfd_generic_link_hide_symbol
6788
#define som_bfd_define_start_stop   bfd_generic_define_start_stop
6789
#define som_bfd_merge_private_bfd_data    _bfd_generic_bfd_merge_private_bfd_data
6790
#define som_bfd_copy_private_header_data  _bfd_generic_bfd_copy_private_header_data
6791
#define som_bfd_set_private_flags   _bfd_generic_bfd_set_private_flags
6792
#define som_find_inliner_info     _bfd_nosymbols_find_inliner_info
6793
#define som_bfd_link_check_relocs   _bfd_generic_link_check_relocs
6794
#define som_finalize_section_relocs   _bfd_generic_finalize_section_relocs
6795
6796
const bfd_target hppa_som_vec =
6797
{
6798
  "som",      /* Name.  */
6799
  bfd_target_som_flavour,
6800
  BFD_ENDIAN_BIG,   /* Target byte order.  */
6801
  BFD_ENDIAN_BIG,   /* Target headers byte order.  */
6802
  (HAS_RELOC | EXEC_P |   /* Object flags.  */
6803
   HAS_LINENO | HAS_DEBUG |
6804
   HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED | DYNAMIC),
6805
  (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS | SEC_LINK_ONCE
6806
   | SEC_ALLOC | SEC_LOAD | SEC_RELOC),   /* Section flags.  */
6807
6808
  /* Leading_symbol_char: is the first char of a user symbol
6809
     predictable, and if so what is it.  */
6810
  0,
6811
  '/',        /* AR_pad_char.  */
6812
  14,       /* AR_max_namelen.  */
6813
  0,        /* match priority.  */
6814
  TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols.  */
6815
  TARGET_MERGE_SECTIONS,
6816
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
6817
  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
6818
  bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Data.  */
6819
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
6820
  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
6821
  bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Headers.  */
6822
  {_bfd_dummy_target,
6823
   som_object_p,    /* bfd_check_format.  */
6824
   bfd_generic_archive_p,
6825
   _bfd_dummy_target
6826
  },
6827
  {
6828
    _bfd_bool_bfd_false_error,
6829
    som_mkobject,
6830
    _bfd_generic_mkarchive,
6831
    _bfd_bool_bfd_false_error
6832
  },
6833
  {
6834
    _bfd_bool_bfd_false_error,
6835
    som_write_object_contents,
6836
    _bfd_write_archive_contents,
6837
    _bfd_bool_bfd_false_error,
6838
  },
6839
#undef som
6840
6841
  BFD_JUMP_TABLE_GENERIC (som),
6842
  BFD_JUMP_TABLE_COPY (som),
6843
  BFD_JUMP_TABLE_CORE (_bfd_nocore),
6844
  BFD_JUMP_TABLE_ARCHIVE (som),
6845
  BFD_JUMP_TABLE_SYMBOLS (som),
6846
  BFD_JUMP_TABLE_RELOCS (som),
6847
  BFD_JUMP_TABLE_WRITE (som),
6848
  BFD_JUMP_TABLE_LINK (som),
6849
  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
6850
6851
  NULL,
6852
6853
  NULL
6854
};
6855