Coverage Report

Created: 2025-06-24 06:45

/src/binutils-gdb/bfd/som.c
Line
Count
Source (jump to first uncovered line)
1
/* bfd back-end for HP PA-RISC SOM objects.
2
   Copyright (C) 1990-2025 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
2.52M
#define CPU_PA_RISC1_0 0x20B
47
#endif /* CPU_PA_RISC1_0 */
48
49
#ifndef CPU_PA_RISC1_1
50
5.04M
#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
2.52M
#define _PA_RISC1_0_ID CPU_PA_RISC1_0
59
#endif /* _PA_RISC1_0_ID */
60
61
#ifndef _PA_RISC1_1_ID
62
2.52M
#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
2.21M
#define _PA_RISC_MAXID  0x2FF
71
#endif /* _PA_RISC_MAXID */
72
73
#ifndef _PA_RISC_ID
74
#define _PA_RISC_ID(__m_num)    \
75
2.52M
    (((__m_num) == _PA_RISC1_0_ID) ||  \
76
2.52M
     ((__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
0
#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
0
#define SOM_TMP_BUFSIZE 8192
98
99
/* Size of the hash table in archives.  */
100
0
#define SOM_LST_HASH_SIZE 31
101
102
/* Max number of SOMs to be found in an archive.  */
103
#define SOM_LST_MODULE_LIMIT 1024
104
105
/* Generic alignment macro.  */
106
#define SOM_ALIGN(val, alignment) \
107
0
  (((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
542
{
908
542
  queue[0].reloc = NULL;
909
542
  queue[0].size = 0;
910
542
  queue[1].reloc = NULL;
911
542
  queue[1].size = 0;
912
542
  queue[2].reloc = NULL;
913
542
  queue[2].size = 0;
914
542
  queue[3].reloc = NULL;
915
542
  queue[3].size = 0;
916
542
}
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
9.43k
{
925
9.43k
  queue[3].reloc = queue[2].reloc;
926
9.43k
  queue[3].size = queue[2].size;
927
9.43k
  queue[2].reloc = queue[1].reloc;
928
9.43k
  queue[2].size = queue[1].size;
929
9.43k
  queue[1].reloc = queue[0].reloc;
930
9.43k
  queue[1].size = queue[0].size;
931
9.43k
  queue[0].reloc = p;
932
9.43k
  queue[0].size = size;
933
9.43k
}
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
1.35k
    return;
943
944
9.61k
  if (idx == 1)
945
7.71k
    {
946
7.71k
      unsigned char *tmp1 = queue[0].reloc;
947
7.71k
      unsigned int tmp2 = queue[0].size;
948
949
7.71k
      queue[0].reloc = queue[1].reloc;
950
7.71k
      queue[0].size = queue[1].size;
951
7.71k
      queue[1].reloc = tmp1;
952
7.71k
      queue[1].size = tmp2;
953
7.71k
      return;
954
7.71k
    }
955
956
1.90k
  if (idx == 2)
957
1.09k
    {
958
1.09k
      unsigned char *tmp1 = queue[0].reloc;
959
1.09k
      unsigned int tmp2 = queue[0].size;
960
961
1.09k
      queue[0].reloc = queue[2].reloc;
962
1.09k
      queue[0].size = queue[2].size;
963
1.09k
      queue[2].reloc = queue[1].reloc;
964
1.09k
      queue[2].size = queue[1].size;
965
1.09k
      queue[1].reloc = tmp1;
966
1.09k
      queue[1].size = tmp2;
967
1.09k
      return;
968
1.09k
    }
969
970
802
  if (idx == 3)
971
802
    {
972
802
      unsigned char *tmp1 = queue[0].reloc;
973
802
      unsigned int tmp2 = queue[0].size;
974
975
802
      queue[0].reloc = queue[3].reloc;
976
802
      queue[0].size = queue[3].size;
977
802
      queue[3].reloc = queue[2].reloc;
978
802
      queue[3].size = queue[2].size;
979
802
      queue[2].reloc = queue[1].reloc;
980
802
      queue[2].size = queue[1].size;
981
802
      queue[1].reloc = tmp1;
982
802
      queue[1].size = tmp2;
983
802
      return;
984
802
    }
985
802
  abort ();
986
802
}
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
0
{
995
0
  if (queue[0].reloc && !memcmp (p, queue[0].reloc, size)
996
0
      && size == queue[0].size)
997
0
    return 0;
998
0
  if (queue[1].reloc && !memcmp (p, queue[1].reloc, size)
999
0
      && size == queue[1].size)
1000
0
    return 1;
1001
0
  if (queue[2].reloc && !memcmp (p, queue[2].reloc, size)
1002
0
      && size == queue[2].size)
1003
0
    return 2;
1004
0
  if (queue[3].reloc && !memcmp (p, queue[3].reloc, size)
1005
0
      && size == queue[3].size)
1006
0
    return 3;
1007
0
  return -1;
1008
0
}
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
0
{
1017
0
  int queue_index = som_reloc_queue_find (p, size, queue);
1018
1019
0
  if (queue_index != -1)
1020
0
    {
1021
      /* Found this in a previous fixup.  Undo the fixup we
1022
   just built and use R_PREV_FIXUP instead.  We saved
1023
   a total of size - 1 bytes in the fixup stream.  */
1024
0
      bfd_put_8 (abfd, R_PREV_FIXUP + queue_index, p);
1025
0
      p += 1;
1026
0
      *subspace_reloc_sizep += 1;
1027
0
      som_reloc_queue_fix (queue, queue_index);
1028
0
    }
1029
0
  else
1030
0
    {
1031
0
      som_reloc_queue_insert (p, size, queue);
1032
0
      *subspace_reloc_sizep += size;
1033
0
      p += size;
1034
0
    }
1035
0
  return p;
1036
0
}
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
0
{
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
0
  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
0
  if ((skip & 3) == 0 && skip <= 0xc0000 && skip > 0)
1074
0
    {
1075
      /* Difference can be handled in a simple single-byte
1076
   R_NO_RELOCATION entry.  */
1077
0
      if (skip <= 0x60)
1078
0
  {
1079
0
    bfd_put_8 (abfd, R_NO_RELOCATION + (skip >> 2) - 1, p);
1080
0
    *subspace_reloc_sizep += 1;
1081
0
    p++;
1082
0
  }
1083
      /* Handle it with a two byte R_NO_RELOCATION entry.  */
1084
0
      else if (skip <= 0x1000)
1085
0
  {
1086
0
    bfd_put_8 (abfd, R_NO_RELOCATION + 24 + (((skip >> 2) - 1) >> 8), p);
1087
0
    bfd_put_8 (abfd, (skip >> 2) - 1, p + 1);
1088
0
    p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 2, queue);
1089
0
  }
1090
      /* Handle it with a three byte R_NO_RELOCATION entry.  */
1091
0
      else
1092
0
  {
1093
0
    bfd_put_8 (abfd, R_NO_RELOCATION + 28 + (((skip >> 2) - 1) >> 16), p);
1094
0
    bfd_put_16 (abfd, (bfd_vma) (skip >> 2) - 1, p + 1);
1095
0
    p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 3, queue);
1096
0
  }
1097
0
    }
1098
  /* Ugh.  Punt and use a 4 byte entry.  */
1099
0
  else if (skip > 0)
1100
0
    {
1101
0
      bfd_put_8 (abfd, R_NO_RELOCATION + 31, p);
1102
0
      bfd_put_8 (abfd, (skip - 1) >> 16, p + 1);
1103
0
      bfd_put_16 (abfd, (bfd_vma) skip - 1, p + 2);
1104
0
      p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 4, queue);
1105
0
    }
1106
0
  return p;
1107
0
}
1108
1109
/* Emit the proper R_DATA_OVERRIDE fixups to handle a nonzero addend
1110
   from a BFD relocation.  Update the size of the subspace relocation
1111
   stream via SUBSPACE_RELOC_SIZE_P; also return the current pointer
1112
   into the relocation stream.  */
1113
1114
static unsigned char *
1115
som_reloc_addend (bfd *abfd,
1116
      bfd_vma addend,
1117
      unsigned char *p,
1118
      unsigned int *subspace_reloc_sizep,
1119
      struct reloc_queue *queue)
1120
0
{
1121
0
  if (addend + 0x80 < 0x100)
1122
0
    {
1123
0
      bfd_put_8 (abfd, R_DATA_OVERRIDE + 1, p);
1124
0
      bfd_put_8 (abfd, addend, p + 1);
1125
0
      p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 2, queue);
1126
0
    }
1127
0
  else if (addend + 0x8000 < 0x10000)
1128
0
    {
1129
0
      bfd_put_8 (abfd, R_DATA_OVERRIDE + 2, p);
1130
0
      bfd_put_16 (abfd, addend, p + 1);
1131
0
      p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 3, queue);
1132
0
    }
1133
0
  else if (addend + 0x800000 < 0x1000000)
1134
0
    {
1135
0
      bfd_put_8 (abfd, R_DATA_OVERRIDE + 3, p);
1136
0
      bfd_put_8 (abfd, addend >> 16, p + 1);
1137
0
      bfd_put_16 (abfd, addend, p + 2);
1138
0
      p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 4, queue);
1139
0
    }
1140
0
  else
1141
0
    {
1142
0
      bfd_put_8 (abfd, R_DATA_OVERRIDE + 4, p);
1143
0
      bfd_put_32 (abfd, addend, p + 1);
1144
0
      p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 5, queue);
1145
0
    }
1146
0
  return p;
1147
0
}
1148
1149
/* Handle a single function call relocation.  */
1150
1151
static unsigned char *
1152
som_reloc_call (bfd *abfd,
1153
    unsigned char *p,
1154
    unsigned int *subspace_reloc_sizep,
1155
    arelent *bfd_reloc,
1156
    int sym_num,
1157
    struct reloc_queue *queue)
1158
0
{
1159
0
  int arg_bits = HPPA_R_ARG_RELOC (bfd_reloc->addend);
1160
0
  int rtn_bits = arg_bits & 0x3;
1161
0
  int type, done = 0;
1162
1163
  /* You'll never believe all this is necessary to handle relocations
1164
     for function calls.  Having to compute and pack the argument
1165
     relocation bits is the real nightmare.
1166
1167
     If you're interested in how this works, just forget it.  You really
1168
     do not want to know about this braindamage.  */
1169
1170
  /* First see if this can be done with a "simple" relocation.  Simple
1171
     relocations have a symbol number < 0x100 and have simple encodings
1172
     of argument relocations.  */
1173
1174
0
  if (sym_num < 0x100)
1175
0
    {
1176
0
      switch (arg_bits)
1177
0
  {
1178
0
  case 0:
1179
0
  case 1:
1180
0
    type = 0;
1181
0
    break;
1182
0
  case 1 << 8:
1183
0
  case 1 << 8 | 1:
1184
0
    type = 1;
1185
0
    break;
1186
0
  case 1 << 8 | 1 << 6:
1187
0
  case 1 << 8 | 1 << 6 | 1:
1188
0
    type = 2;
1189
0
    break;
1190
0
  case 1 << 8 | 1 << 6 | 1 << 4:
1191
0
  case 1 << 8 | 1 << 6 | 1 << 4 | 1:
1192
0
    type = 3;
1193
0
    break;
1194
0
  case 1 << 8 | 1 << 6 | 1 << 4 | 1 << 2:
1195
0
  case 1 << 8 | 1 << 6 | 1 << 4 | 1 << 2 | 1:
1196
0
    type = 4;
1197
0
    break;
1198
0
  default:
1199
    /* Not one of the easy encodings.  This will have to be
1200
       handled by the more complex code below.  */
1201
0
    type = -1;
1202
0
    break;
1203
0
  }
1204
0
      if (type != -1)
1205
0
  {
1206
    /* Account for the return value too.  */
1207
0
    if (rtn_bits)
1208
0
      type += 5;
1209
1210
    /* Emit a 2 byte relocation.  Then see if it can be handled
1211
       with a relocation which is already in the relocation queue.  */
1212
0
    bfd_put_8 (abfd, bfd_reloc->howto->type + type, p);
1213
0
    bfd_put_8 (abfd, sym_num, p + 1);
1214
0
    p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 2, queue);
1215
0
    done = 1;
1216
0
  }
1217
0
    }
1218
1219
  /* If this could not be handled with a simple relocation, then do a hard
1220
     one.  Hard relocations occur if the symbol number was too high or if
1221
     the encoding of argument relocation bits is too complex.  */
1222
0
  if (! done)
1223
0
    {
1224
      /* Don't ask about these magic sequences.  I took them straight
1225
   from gas-1.36 which took them from the a.out man page.  */
1226
0
      type = rtn_bits;
1227
0
      if ((arg_bits >> 6 & 0xf) == 0xe)
1228
0
  type += 9 * 40;
1229
0
      else
1230
0
  type += (3 * (arg_bits >> 8 & 3) + (arg_bits >> 6 & 3)) * 40;
1231
0
      if ((arg_bits >> 2 & 0xf) == 0xe)
1232
0
  type += 9 * 4;
1233
0
      else
1234
0
  type += (3 * (arg_bits >> 4 & 3) + (arg_bits >> 2 & 3)) * 4;
1235
1236
      /* Output the first two bytes of the relocation.  These describe
1237
   the length of the relocation and encoding style.  */
1238
0
      bfd_put_8 (abfd, bfd_reloc->howto->type + 10
1239
0
     + 2 * (sym_num >= 0x100) + (type >= 0x100),
1240
0
     p);
1241
0
      bfd_put_8 (abfd, type, p + 1);
1242
1243
      /* Now output the symbol index and see if this bizarre relocation
1244
   just happened to be in the relocation queue.  */
1245
0
      if (sym_num < 0x100)
1246
0
  {
1247
0
    bfd_put_8 (abfd, sym_num, p + 2);
1248
0
    p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 3, queue);
1249
0
  }
1250
0
      else
1251
0
  {
1252
0
    bfd_put_8 (abfd, sym_num >> 16, p + 2);
1253
0
    bfd_put_16 (abfd, (bfd_vma) sym_num, p + 3);
1254
0
    p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 5, queue);
1255
0
  }
1256
0
    }
1257
0
  return p;
1258
0
}
1259
1260
/* Return the logarithm of X, base 2, considering X unsigned,
1261
   if X is a power of 2.  Otherwise, returns -1.  */
1262
1263
static int
1264
exact_log2 (unsigned int x)
1265
67.3k
{
1266
67.3k
  int log = 0;
1267
1268
  /* Test for 0 or a power of 2.  */
1269
67.3k
  if (x == 0 || x != (x & -x))
1270
4.25k
    return -1;
1271
1272
787k
  while ((x >>= 1) != 0)
1273
724k
    log++;
1274
63.0k
  return log;
1275
67.3k
}
1276
1277
static bfd_reloc_status_type
1278
hppa_som_reloc (bfd *abfd ATTRIBUTE_UNUSED,
1279
    arelent *reloc_entry,
1280
    asymbol *symbol_in ATTRIBUTE_UNUSED,
1281
    void *data ATTRIBUTE_UNUSED,
1282
    asection *input_section,
1283
    bfd *output_bfd,
1284
    char **error_message ATTRIBUTE_UNUSED)
1285
0
{
1286
0
  if (output_bfd)
1287
0
    reloc_entry->address += input_section->output_offset;
1288
1289
0
  return bfd_reloc_ok;
1290
0
}
1291
1292
/* Given a generic HPPA relocation type, the instruction format,
1293
   and a field selector, return one or more appropriate SOM relocations.  */
1294
1295
int **
1296
hppa_som_gen_reloc_type (bfd *abfd,
1297
       int base_type,
1298
       int format,
1299
       enum hppa_reloc_field_selector_type_alt field,
1300
       int sym_diff,
1301
       asymbol *sym)
1302
0
{
1303
0
  int *final_type, **final_types;
1304
1305
0
  final_types = bfd_alloc (abfd, (bfd_size_type) sizeof (int *) * 6);
1306
0
  final_type = bfd_alloc (abfd, (bfd_size_type) sizeof (int));
1307
0
  if (!final_types || !final_type)
1308
0
    return NULL;
1309
1310
  /* The field selector may require additional relocations to be
1311
     generated.  It's impossible to know at this moment if additional
1312
     relocations will be needed, so we make them.  The code to actually
1313
     write the relocation/fixup stream is responsible for removing
1314
     any redundant relocations.  */
1315
0
  switch (field)
1316
0
    {
1317
0
    case e_fsel:
1318
0
    case e_psel:
1319
0
    case e_lpsel:
1320
0
    case e_rpsel:
1321
0
      final_types[0] = final_type;
1322
0
      final_types[1] = NULL;
1323
0
      final_types[2] = NULL;
1324
0
      *final_type = base_type;
1325
0
      break;
1326
1327
0
    case e_tsel:
1328
0
    case e_ltsel:
1329
0
    case e_rtsel:
1330
0
      final_types[0] = bfd_alloc (abfd, (bfd_size_type) sizeof (int));
1331
0
      if (!final_types[0])
1332
0
  return NULL;
1333
0
      if (field == e_tsel)
1334
0
  *final_types[0] = R_FSEL;
1335
0
      else if (field == e_ltsel)
1336
0
  *final_types[0] = R_LSEL;
1337
0
      else
1338
0
  *final_types[0] = R_RSEL;
1339
0
      final_types[1] = final_type;
1340
0
      final_types[2] = NULL;
1341
0
      *final_type = base_type;
1342
0
      break;
1343
1344
0
    case e_lssel:
1345
0
    case e_rssel:
1346
0
      final_types[0] = bfd_alloc (abfd, (bfd_size_type) sizeof (int));
1347
0
      if (!final_types[0])
1348
0
  return NULL;
1349
0
      *final_types[0] = R_S_MODE;
1350
0
      final_types[1] = final_type;
1351
0
      final_types[2] = NULL;
1352
0
      *final_type = base_type;
1353
0
      break;
1354
1355
0
    case e_lsel:
1356
0
    case e_rsel:
1357
0
      final_types[0] = bfd_alloc (abfd, (bfd_size_type) sizeof (int));
1358
0
      if (!final_types[0])
1359
0
  return NULL;
1360
0
      *final_types[0] = R_N_MODE;
1361
0
      final_types[1] = final_type;
1362
0
      final_types[2] = NULL;
1363
0
      *final_type = base_type;
1364
0
      break;
1365
1366
0
    case e_ldsel:
1367
0
    case e_rdsel:
1368
0
      final_types[0] = bfd_alloc (abfd, (bfd_size_type) sizeof (int));
1369
0
      if (!final_types[0])
1370
0
  return NULL;
1371
0
      *final_types[0] = R_D_MODE;
1372
0
      final_types[1] = final_type;
1373
0
      final_types[2] = NULL;
1374
0
      *final_type = base_type;
1375
0
      break;
1376
1377
0
    case e_lrsel:
1378
0
    case e_rrsel:
1379
0
      final_types[0] = bfd_alloc (abfd, (bfd_size_type) sizeof (int));
1380
0
      if (!final_types[0])
1381
0
  return NULL;
1382
0
      *final_types[0] = R_R_MODE;
1383
0
      final_types[1] = final_type;
1384
0
      final_types[2] = NULL;
1385
0
      *final_type = base_type;
1386
0
      break;
1387
1388
0
    case e_nsel:
1389
0
      final_types[0] = bfd_alloc (abfd, (bfd_size_type) sizeof (int));
1390
0
      if (!final_types[0])
1391
0
  return NULL;
1392
0
      *final_types[0] = R_N1SEL;
1393
0
      final_types[1] = final_type;
1394
0
      final_types[2] = NULL;
1395
0
      *final_type = base_type;
1396
0
      break;
1397
1398
0
    case e_nlsel:
1399
0
    case e_nlrsel:
1400
0
      final_types[0] = bfd_alloc (abfd, (bfd_size_type) sizeof (int));
1401
0
      if (!final_types[0])
1402
0
  return NULL;
1403
0
      *final_types[0] = R_N0SEL;
1404
0
      final_types[1] = bfd_alloc (abfd, (bfd_size_type) sizeof (int));
1405
0
      if (!final_types[1])
1406
0
  return NULL;
1407
0
      if (field == e_nlsel)
1408
0
  *final_types[1] = R_N_MODE;
1409
0
      else
1410
0
  *final_types[1] = R_R_MODE;
1411
0
      final_types[2] = final_type;
1412
0
      final_types[3] = NULL;
1413
0
      *final_type = base_type;
1414
0
      break;
1415
1416
    /* FIXME: These two field selectors are not currently supported.  */
1417
0
    case e_ltpsel:
1418
0
    case e_rtpsel:
1419
0
      abort ();
1420
0
    }
1421
1422
0
  switch (base_type)
1423
0
    {
1424
0
    case R_HPPA:
1425
      /* The difference of two symbols needs *very* special handling.  */
1426
0
      if (sym_diff)
1427
0
  {
1428
0
    size_t amt = sizeof (int);
1429
1430
0
    final_types[0] = bfd_alloc (abfd, amt);
1431
0
    final_types[1] = bfd_alloc (abfd, amt);
1432
0
    final_types[2] = bfd_alloc (abfd, amt);
1433
0
    final_types[3] = bfd_alloc (abfd, amt);
1434
0
    if (!final_types[0] || !final_types[1] || !final_types[2])
1435
0
      return NULL;
1436
0
    if (field == e_fsel)
1437
0
      *final_types[0] = R_FSEL;
1438
0
    else if (field == e_rsel)
1439
0
      *final_types[0] = R_RSEL;
1440
0
    else if (field == e_lsel)
1441
0
      *final_types[0] = R_LSEL;
1442
0
    *final_types[1] = R_COMP2;
1443
0
    *final_types[2] = R_COMP2;
1444
0
    *final_types[3] = R_COMP1;
1445
0
    final_types[4] = final_type;
1446
0
    if (format == 32)
1447
0
      *final_types[4] = R_DATA_EXPR;
1448
0
    else
1449
0
      *final_types[4] = R_CODE_EXPR;
1450
0
    final_types[5] = NULL;
1451
0
    break;
1452
0
  }
1453
      /* PLABELs get their own relocation type.  */
1454
0
      else if (field == e_psel
1455
0
         || field == e_lpsel
1456
0
         || field == e_rpsel)
1457
0
  {
1458
    /* A PLABEL relocation that has a size of 32 bits must
1459
       be a R_DATA_PLABEL.  All others are R_CODE_PLABELs.  */
1460
0
    if (format == 32)
1461
0
      *final_type = R_DATA_PLABEL;
1462
0
    else
1463
0
      *final_type = R_CODE_PLABEL;
1464
0
  }
1465
      /* PIC stuff.  */
1466
0
      else if (field == e_tsel
1467
0
         || field == e_ltsel
1468
0
         || field == e_rtsel)
1469
0
  *final_type = R_DLT_REL;
1470
      /* A relocation in the data space is always a full 32bits.  */
1471
0
      else if (format == 32)
1472
0
  {
1473
0
    *final_type = R_DATA_ONE_SYMBOL;
1474
1475
    /* If there's no SOM symbol type associated with this BFD
1476
       symbol, then set the symbol type to ST_DATA.
1477
1478
       Only do this if the type is going to default later when
1479
       we write the object file.
1480
1481
       This is done so that the linker never encounters an
1482
       R_DATA_ONE_SYMBOL reloc involving an ST_CODE symbol.
1483
1484
       This allows the compiler to generate exception handling
1485
       tables.
1486
1487
       Note that one day we may need to also emit BEGIN_BRTAB and
1488
       END_BRTAB to prevent the linker from optimizing away insns
1489
       in exception handling regions.  */
1490
0
    if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN
1491
0
        && (sym->flags & BSF_SECTION_SYM) == 0
1492
0
        && (sym->flags & BSF_FUNCTION) == 0
1493
0
        && ! bfd_is_com_section (sym->section))
1494
0
      som_symbol_data (sym)->som_type = SYMBOL_TYPE_DATA;
1495
0
  }
1496
0
      break;
1497
1498
0
    case R_HPPA_GOTOFF:
1499
      /* More PLABEL special cases.  */
1500
0
      if (field == e_psel
1501
0
    || field == e_lpsel
1502
0
    || field == e_rpsel)
1503
0
  *final_type = R_DATA_PLABEL;
1504
0
      else if (field == e_fsel && format == 32)
1505
0
  *final_type = R_DATA_GPREL;
1506
0
      break;
1507
1508
0
    case R_HPPA_COMPLEX:
1509
      /* The difference of two symbols needs *very* special handling.  */
1510
0
      if (sym_diff)
1511
0
  {
1512
0
    size_t amt = sizeof (int);
1513
1514
0
    final_types[0] = bfd_alloc (abfd, amt);
1515
0
    final_types[1] = bfd_alloc (abfd, amt);
1516
0
    final_types[2] = bfd_alloc (abfd, amt);
1517
0
    final_types[3] = bfd_alloc (abfd, amt);
1518
0
    if (!final_types[0] || !final_types[1] || !final_types[2])
1519
0
      return NULL;
1520
0
    if (field == e_fsel)
1521
0
      *final_types[0] = R_FSEL;
1522
0
    else if (field == e_rsel)
1523
0
      *final_types[0] = R_RSEL;
1524
0
    else if (field == e_lsel)
1525
0
      *final_types[0] = R_LSEL;
1526
0
    *final_types[1] = R_COMP2;
1527
0
    *final_types[2] = R_COMP2;
1528
0
    *final_types[3] = R_COMP1;
1529
0
    final_types[4] = final_type;
1530
0
    if (format == 32)
1531
0
      *final_types[4] = R_DATA_EXPR;
1532
0
    else
1533
0
      *final_types[4] = R_CODE_EXPR;
1534
0
    final_types[5] = NULL;
1535
0
    break;
1536
0
  }
1537
0
      else
1538
0
  break;
1539
1540
0
    case R_HPPA_NONE:
1541
0
    case R_HPPA_ABS_CALL:
1542
      /* Right now we can default all these.  */
1543
0
      break;
1544
1545
0
    case R_HPPA_PCREL_CALL:
1546
0
      {
1547
0
#ifndef NO_PCREL_MODES
1548
  /* If we have short and long pcrel modes, then generate the proper
1549
     mode selector, then the pcrel relocation.  Redundant selectors
1550
     will be eliminated as the relocs are sized and emitted.  */
1551
0
  size_t amt = sizeof (int);
1552
1553
0
  final_types[0] = bfd_alloc (abfd, amt);
1554
0
  if (!final_types[0])
1555
0
    return NULL;
1556
0
  if (format == 17)
1557
0
    *final_types[0] = R_SHORT_PCREL_MODE;
1558
0
  else
1559
0
    *final_types[0] = R_LONG_PCREL_MODE;
1560
0
  final_types[1] = final_type;
1561
0
  final_types[2] = NULL;
1562
0
  *final_type = base_type;
1563
0
#endif
1564
0
  break;
1565
0
      }
1566
0
    }
1567
0
  return final_types;
1568
0
}
1569
1570
/* Return the address of the correct entry in the PA SOM relocation
1571
   howto table.  */
1572
1573
static reloc_howto_type *
1574
som_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
1575
         bfd_reloc_code_real_type code)
1576
0
{
1577
0
  if ((int) code < (int) R_NO_RELOCATION + 255)
1578
0
    {
1579
0
      BFD_ASSERT ((int) som_hppa_howto_table[(int) code].type == (int) code);
1580
0
      return &som_hppa_howto_table[(int) code];
1581
0
    }
1582
1583
0
  return NULL;
1584
0
}
1585
1586
static reloc_howto_type *
1587
som_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
1588
         const char *r_name)
1589
0
{
1590
0
  unsigned int i;
1591
1592
0
  for (i = 0;
1593
0
       i < sizeof (som_hppa_howto_table) / sizeof (som_hppa_howto_table[0]);
1594
0
       i++)
1595
0
    if (som_hppa_howto_table[i].name != NULL
1596
0
  && strcasecmp (som_hppa_howto_table[i].name, r_name) == 0)
1597
0
      return &som_hppa_howto_table[i];
1598
1599
0
  return NULL;
1600
0
}
1601
1602
static void
1603
som_swap_clock_in (struct som_external_clock *src,
1604
       struct som_clock *dst)
1605
2.52M
{
1606
2.52M
  dst->secs = bfd_getb32 (src->secs);
1607
2.52M
  dst->nanosecs = bfd_getb32 (src->nanosecs);
1608
2.52M
}
1609
1610
static void
1611
som_swap_clock_out (struct som_clock *src,
1612
        struct som_external_clock *dst)
1613
0
{
1614
0
  bfd_putb32 (src->secs, dst->secs);
1615
0
  bfd_putb32 (src->nanosecs, dst->nanosecs);
1616
0
}
1617
1618
static void
1619
som_swap_header_in (struct som_external_header *src,
1620
        struct som_header *dst)
1621
2.52M
{
1622
2.52M
  dst->system_id = bfd_getb16 (src->system_id);
1623
2.52M
  dst->a_magic = bfd_getb16 (src->a_magic);
1624
2.52M
  dst->version_id = bfd_getb32 (src->version_id);
1625
2.52M
  som_swap_clock_in (&src->file_time, &dst->file_time);
1626
2.52M
  dst->entry_space = bfd_getb32 (src->entry_space);
1627
2.52M
  dst->entry_subspace = bfd_getb32 (src->entry_subspace);
1628
2.52M
  dst->entry_offset = bfd_getb32 (src->entry_offset);
1629
2.52M
  dst->aux_header_location = bfd_getb32 (src->aux_header_location);
1630
2.52M
  dst->aux_header_size = bfd_getb32 (src->aux_header_size);
1631
2.52M
  dst->som_length = bfd_getb32 (src->som_length);
1632
2.52M
  dst->presumed_dp = bfd_getb32 (src->presumed_dp);
1633
2.52M
  dst->space_location = bfd_getb32 (src->space_location);
1634
2.52M
  dst->space_total = bfd_getb32 (src->space_total);
1635
2.52M
  dst->subspace_location = bfd_getb32 (src->subspace_location);
1636
2.52M
  dst->subspace_total = bfd_getb32 (src->subspace_total);
1637
2.52M
  dst->loader_fixup_location = bfd_getb32 (src->loader_fixup_location);
1638
2.52M
  dst->loader_fixup_total = bfd_getb32 (src->loader_fixup_total);
1639
2.52M
  dst->space_strings_location = bfd_getb32 (src->space_strings_location);
1640
2.52M
  dst->space_strings_size = bfd_getb32 (src->space_strings_size);
1641
2.52M
  dst->init_array_location = bfd_getb32 (src->init_array_location);
1642
2.52M
  dst->init_array_total = bfd_getb32 (src->init_array_total);
1643
2.52M
  dst->compiler_location = bfd_getb32 (src->compiler_location);
1644
2.52M
  dst->compiler_total = bfd_getb32 (src->compiler_total);
1645
2.52M
  dst->symbol_location = bfd_getb32 (src->symbol_location);
1646
2.52M
  dst->symbol_total = bfd_getb32 (src->symbol_total);
1647
2.52M
  dst->fixup_request_location = bfd_getb32 (src->fixup_request_location);
1648
2.52M
  dst->fixup_request_total = bfd_getb32 (src->fixup_request_total);
1649
2.52M
  dst->symbol_strings_location = bfd_getb32 (src->symbol_strings_location);
1650
2.52M
  dst->symbol_strings_size = bfd_getb32 (src->symbol_strings_size);
1651
2.52M
  dst->unloadable_sp_location = bfd_getb32 (src->unloadable_sp_location);
1652
2.52M
  dst->unloadable_sp_size = bfd_getb32 (src->unloadable_sp_size);
1653
2.52M
  dst->checksum = bfd_getb32 (src->checksum);
1654
2.52M
}
1655
1656
static void
1657
som_swap_header_out (struct som_header *src,
1658
        struct som_external_header *dst)
1659
0
{
1660
0
  bfd_putb16 (src->system_id, dst->system_id);
1661
0
  bfd_putb16 (src->a_magic, dst->a_magic);
1662
0
  bfd_putb32 (src->version_id, dst->version_id);
1663
0
  som_swap_clock_out (&src->file_time, &dst->file_time);
1664
0
  bfd_putb32 (src->entry_space, dst->entry_space);
1665
0
  bfd_putb32 (src->entry_subspace, dst->entry_subspace);
1666
0
  bfd_putb32 (src->entry_offset, dst->entry_offset);
1667
0
  bfd_putb32 (src->aux_header_location, dst->aux_header_location);
1668
0
  bfd_putb32 (src->aux_header_size, dst->aux_header_size);
1669
0
  bfd_putb32 (src->som_length, dst->som_length);
1670
0
  bfd_putb32 (src->presumed_dp, dst->presumed_dp);
1671
0
  bfd_putb32 (src->space_location, dst->space_location);
1672
0
  bfd_putb32 (src->space_total, dst->space_total);
1673
0
  bfd_putb32 (src->subspace_location, dst->subspace_location);
1674
0
  bfd_putb32 (src->subspace_total, dst->subspace_total);
1675
0
  bfd_putb32 (src->loader_fixup_location, dst->loader_fixup_location);
1676
0
  bfd_putb32 (src->loader_fixup_total, dst->loader_fixup_total);
1677
0
  bfd_putb32 (src->space_strings_location, dst->space_strings_location);
1678
0
  bfd_putb32 (src->space_strings_size, dst->space_strings_size);
1679
0
  bfd_putb32 (src->init_array_location, dst->init_array_location);
1680
0
  bfd_putb32 (src->init_array_total, dst->init_array_total);
1681
0
  bfd_putb32 (src->compiler_location, dst->compiler_location);
1682
0
  bfd_putb32 (src->compiler_total, dst->compiler_total);
1683
0
  bfd_putb32 (src->symbol_location, dst->symbol_location);
1684
0
  bfd_putb32 (src->symbol_total, dst->symbol_total);
1685
0
  bfd_putb32 (src->fixup_request_location, dst->fixup_request_location);
1686
0
  bfd_putb32 (src->fixup_request_total, dst->fixup_request_total);
1687
0
  bfd_putb32 (src->symbol_strings_location, dst->symbol_strings_location);
1688
0
  bfd_putb32 (src->symbol_strings_size, dst->symbol_strings_size);
1689
0
  bfd_putb32 (src->unloadable_sp_location, dst->unloadable_sp_location);
1690
0
  bfd_putb32 (src->unloadable_sp_size, dst->unloadable_sp_size);
1691
0
  bfd_putb32 (src->checksum, dst->checksum);
1692
0
}
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
33.2k
{
1698
33.2k
  unsigned int flags;
1699
1700
33.2k
  dst->name = bfd_getb32 (src->name);
1701
33.2k
  flags = bfd_getb32 (src->flags);
1702
33.2k
  dst->is_loadable = (flags & SOM_SPACE_IS_LOADABLE) != 0;
1703
33.2k
  dst->is_defined = (flags & SOM_SPACE_IS_DEFINED) != 0;
1704
33.2k
  dst->is_private = (flags & SOM_SPACE_IS_PRIVATE) != 0;
1705
33.2k
  dst->has_intermediate_code = (flags & SOM_SPACE_HAS_INTERMEDIATE_CODE) != 0;
1706
33.2k
  dst->is_tspecific = (flags & SOM_SPACE_IS_TSPECIFIC) != 0;
1707
33.2k
  dst->reserved = 0;
1708
33.2k
  dst->sort_key = (flags >> SOM_SPACE_SORT_KEY_SH) & SOM_SPACE_SORT_KEY_MASK;
1709
33.2k
  dst->reserved2 = 0;
1710
33.2k
  dst->space_number = bfd_getb32 (src->space_number);
1711
33.2k
  dst->subspace_index = bfd_getb32 (src->subspace_index);
1712
33.2k
  dst->subspace_quantity = bfd_getb32 (src->subspace_quantity);
1713
33.2k
  dst->loader_fix_index = bfd_getb32 (src->loader_fix_index);
1714
33.2k
  dst->loader_fix_quantity = bfd_getb32 (src->loader_fix_quantity);
1715
33.2k
  dst->init_pointer_index = bfd_getb32 (src->init_pointer_index);
1716
33.2k
  dst->init_pointer_quantity = bfd_getb32 (src->init_pointer_quantity);
1717
33.2k
}
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
0
{
1723
0
  unsigned int flags;
1724
1725
0
  bfd_putb32 (src->name, dst->name);
1726
1727
0
  flags = 0;
1728
0
  if (src->is_loadable)
1729
0
    flags |= SOM_SPACE_IS_LOADABLE;
1730
0
  if (src->is_defined)
1731
0
    flags |= SOM_SPACE_IS_DEFINED;
1732
0
  if (src->is_private)
1733
0
    flags |= SOM_SPACE_IS_PRIVATE;
1734
0
  if (src->has_intermediate_code)
1735
0
    flags |= SOM_SPACE_HAS_INTERMEDIATE_CODE;
1736
0
  if (src->is_tspecific)
1737
0
    flags |= SOM_SPACE_IS_TSPECIFIC;
1738
0
  flags |= (src->sort_key & SOM_SPACE_SORT_KEY_MASK) << SOM_SPACE_SORT_KEY_SH;
1739
0
  bfd_putb32 (flags, dst->flags);
1740
0
  bfd_putb32 (src->space_number, dst->space_number);
1741
0
  bfd_putb32 (src->subspace_index, dst->subspace_index);
1742
0
  bfd_putb32 (src->subspace_quantity, dst->subspace_quantity);
1743
0
  bfd_putb32 (src->loader_fix_index, dst->loader_fix_index);
1744
0
  bfd_putb32 (src->loader_fix_quantity, dst->loader_fix_quantity);
1745
0
  bfd_putb32 (src->init_pointer_index, dst->init_pointer_index);
1746
0
  bfd_putb32 (src->init_pointer_quantity, dst->init_pointer_quantity);
1747
0
}
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
69.3k
{
1754
69.3k
  unsigned int flags;
1755
69.3k
  dst->space_index = bfd_getb32 (src->space_index);
1756
69.3k
  flags = bfd_getb32 (src->flags);
1757
69.3k
  dst->access_control_bits = (flags >> SOM_SUBSPACE_ACCESS_CONTROL_BITS_SH)
1758
69.3k
    & SOM_SUBSPACE_ACCESS_CONTROL_BITS_MASK;
1759
69.3k
  dst->memory_resident = (flags & SOM_SUBSPACE_MEMORY_RESIDENT) != 0;
1760
69.3k
  dst->dup_common = (flags & SOM_SUBSPACE_DUP_COMMON) != 0;
1761
69.3k
  dst->is_common = (flags & SOM_SUBSPACE_IS_COMMON) != 0;
1762
69.3k
  dst->is_loadable = (flags & SOM_SUBSPACE_IS_LOADABLE) != 0;
1763
69.3k
  dst->quadrant = (flags >> SOM_SUBSPACE_QUADRANT_SH)
1764
69.3k
    & SOM_SUBSPACE_QUADRANT_MASK;
1765
69.3k
  dst->initially_frozen = (flags & SOM_SUBSPACE_INITIALLY_FROZEN) != 0;
1766
69.3k
  dst->is_first = (flags & SOM_SUBSPACE_IS_FIRST) != 0;
1767
69.3k
  dst->code_only = (flags & SOM_SUBSPACE_CODE_ONLY) != 0;
1768
69.3k
  dst->sort_key = (flags >> SOM_SUBSPACE_SORT_KEY_SH)
1769
69.3k
    & SOM_SUBSPACE_SORT_KEY_MASK;
1770
69.3k
  dst->replicate_init = (flags & SOM_SUBSPACE_REPLICATE_INIT) != 0;
1771
69.3k
  dst->continuation = (flags & SOM_SUBSPACE_CONTINUATION) != 0;
1772
69.3k
  dst->is_tspecific = (flags & SOM_SUBSPACE_IS_TSPECIFIC) != 0;
1773
69.3k
  dst->is_comdat = (flags & SOM_SUBSPACE_IS_COMDAT) != 0;
1774
69.3k
  dst->reserved = 0;
1775
69.3k
  dst->file_loc_init_value = bfd_getb32 (src->file_loc_init_value);
1776
69.3k
  dst->initialization_length = bfd_getb32 (src->initialization_length);
1777
69.3k
  dst->subspace_start = bfd_getb32 (src->subspace_start);
1778
69.3k
  dst->subspace_length = bfd_getb32 (src->subspace_length);
1779
69.3k
  dst->alignment = bfd_getb32 (src->alignment);
1780
69.3k
  dst->name = bfd_getb32 (src->name);
1781
69.3k
  dst->fixup_request_index = bfd_getb32 (src->fixup_request_index);
1782
69.3k
  dst->fixup_request_quantity = bfd_getb32 (src->fixup_request_quantity);
1783
69.3k
}
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
0
{
1790
0
  unsigned int flags;
1791
1792
0
  bfd_putb32 (src->space_index, dst->space_index);
1793
0
  flags = (src->access_control_bits & SOM_SUBSPACE_ACCESS_CONTROL_BITS_MASK)
1794
0
    << SOM_SUBSPACE_ACCESS_CONTROL_BITS_SH;
1795
0
  if (src->memory_resident)
1796
0
    flags |= SOM_SUBSPACE_MEMORY_RESIDENT;
1797
0
  if (src->dup_common)
1798
0
    flags |= SOM_SUBSPACE_DUP_COMMON;
1799
0
  if (src->is_common)
1800
0
    flags |= SOM_SUBSPACE_IS_COMMON;
1801
0
  if (src->is_loadable)
1802
0
    flags |= SOM_SUBSPACE_IS_LOADABLE;
1803
0
  flags |= (src->quadrant & SOM_SUBSPACE_QUADRANT_MASK)
1804
0
    << SOM_SUBSPACE_QUADRANT_SH;
1805
0
  if (src->initially_frozen)
1806
0
    flags |= SOM_SUBSPACE_INITIALLY_FROZEN;
1807
0
  if (src->is_first)
1808
0
    flags |= SOM_SUBSPACE_IS_FIRST;
1809
0
  if (src->code_only)
1810
0
    flags |= SOM_SUBSPACE_CODE_ONLY;
1811
0
  flags |= (src->sort_key & SOM_SUBSPACE_SORT_KEY_MASK)
1812
0
    << SOM_SUBSPACE_SORT_KEY_SH;
1813
0
  if (src->replicate_init)
1814
0
    flags |= SOM_SUBSPACE_REPLICATE_INIT;
1815
0
  if (src->continuation)
1816
0
    flags |= SOM_SUBSPACE_CONTINUATION;
1817
0
  if (src->is_tspecific)
1818
0
    flags |= SOM_SUBSPACE_IS_TSPECIFIC;
1819
0
  if (src->is_comdat)
1820
0
    flags |= SOM_SUBSPACE_IS_COMDAT;
1821
0
  bfd_putb32 (flags, dst->flags);
1822
0
  bfd_putb32 (src->file_loc_init_value, dst->file_loc_init_value);
1823
0
  bfd_putb32 (src->initialization_length, dst->initialization_length);
1824
0
  bfd_putb32 (src->subspace_start, dst->subspace_start);
1825
0
  bfd_putb32 (src->subspace_length, dst->subspace_length);
1826
0
  bfd_putb32 (src->alignment, dst->alignment);
1827
0
  bfd_putb32 (src->name, dst->name);
1828
0
  bfd_putb32 (src->fixup_request_index, dst->fixup_request_index);
1829
0
  bfd_putb32 (src->fixup_request_quantity, dst->fixup_request_quantity);
1830
0
}
1831
1832
static void
1833
som_swap_aux_id_in (struct som_external_aux_id *src,
1834
        struct som_aux_id *dst)
1835
23.9k
{
1836
23.9k
  unsigned int flags = bfd_getb32 (src->flags);
1837
1838
23.9k
  dst->mandatory = (flags & SOM_AUX_ID_MANDATORY) != 0;
1839
23.9k
  dst->copy = (flags & SOM_AUX_ID_COPY) != 0;
1840
23.9k
  dst->append = (flags & SOM_AUX_ID_APPEND) != 0;
1841
23.9k
  dst->ignore = (flags & SOM_AUX_ID_IGNORE) != 0;
1842
23.9k
  dst->type = (flags >> SOM_AUX_ID_TYPE_SH) & SOM_AUX_ID_TYPE_MASK;
1843
23.9k
  dst->length = bfd_getb32 (src->length);
1844
23.9k
}
1845
1846
static void
1847
som_swap_aux_id_out (struct som_aux_id *src,
1848
        struct som_external_aux_id *dst)
1849
0
{
1850
0
  unsigned int flags = 0;
1851
1852
0
  if (src->mandatory)
1853
0
    flags |= SOM_AUX_ID_MANDATORY;
1854
0
  if (src->copy)
1855
0
    flags |= SOM_AUX_ID_COPY;
1856
0
  if (src->append)
1857
0
    flags |= SOM_AUX_ID_APPEND;
1858
0
  if (src->ignore)
1859
0
    flags |= SOM_AUX_ID_IGNORE;
1860
0
  flags |= (src->type & SOM_AUX_ID_TYPE_MASK) << SOM_AUX_ID_TYPE_SH;
1861
0
  bfd_putb32 (flags, dst->flags);
1862
0
  bfd_putb32 (src->length, dst->length);
1863
0
}
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
23.9k
{
1890
23.9k
  som_swap_aux_id_in (&src->som_auxhdr, &dst->som_auxhdr);
1891
23.9k
  dst->exec_tsize = bfd_getb32 (src->exec_tsize);
1892
23.9k
  dst->exec_tmem = bfd_getb32 (src->exec_tmem);
1893
23.9k
  dst->exec_tfile = bfd_getb32 (src->exec_tfile);
1894
23.9k
  dst->exec_dsize = bfd_getb32 (src->exec_dsize);
1895
23.9k
  dst->exec_dmem = bfd_getb32 (src->exec_dmem);
1896
23.9k
  dst->exec_dfile = bfd_getb32 (src->exec_dfile);
1897
23.9k
  dst->exec_bsize = bfd_getb32 (src->exec_bsize);
1898
23.9k
  dst->exec_entry = bfd_getb32 (src->exec_entry);
1899
23.9k
  dst->exec_flags = bfd_getb32 (src->exec_flags);
1900
23.9k
  dst->exec_bfill = bfd_getb32 (src->exec_bfill);
1901
23.9k
}
1902
1903
static void
1904
som_swap_exec_auxhdr_out (struct som_exec_auxhdr *src,
1905
       struct som_external_exec_auxhdr *dst)
1906
0
{
1907
0
  som_swap_aux_id_out (&src->som_auxhdr, &dst->som_auxhdr);
1908
0
  bfd_putb32 (src->exec_tsize, dst->exec_tsize);
1909
0
  bfd_putb32 (src->exec_tmem, dst->exec_tmem);
1910
0
  bfd_putb32 (src->exec_tfile, dst->exec_tfile);
1911
0
  bfd_putb32 (src->exec_dsize, dst->exec_dsize);
1912
0
  bfd_putb32 (src->exec_dmem, dst->exec_dmem);
1913
0
  bfd_putb32 (src->exec_dfile, dst->exec_dfile);
1914
0
  bfd_putb32 (src->exec_bsize, dst->exec_bsize);
1915
0
  bfd_putb32 (src->exec_entry, dst->exec_entry);
1916
0
  bfd_putb32 (src->exec_flags, dst->exec_flags);
1917
0
  bfd_putb32 (src->exec_bfill, dst->exec_bfill);
1918
0
}
1919
1920
static void
1921
som_swap_lst_header_in (struct som_external_lst_header *src,
1922
      struct som_lst_header *dst)
1923
4.98k
{
1924
4.98k
  dst->system_id = bfd_getb16 (src->system_id);
1925
4.98k
  dst->a_magic = bfd_getb16 (src->a_magic);
1926
4.98k
  dst->version_id = bfd_getb32 (src->version_id);
1927
4.98k
  som_swap_clock_in (&src->file_time, &dst->file_time);
1928
4.98k
  dst->hash_loc = bfd_getb32 (src->hash_loc);
1929
4.98k
  dst->hash_size = bfd_getb32 (src->hash_size);
1930
4.98k
  dst->module_count = bfd_getb32 (src->module_count);
1931
4.98k
  dst->module_limit = bfd_getb32 (src->module_limit);
1932
4.98k
  dst->dir_loc = bfd_getb32 (src->dir_loc);
1933
4.98k
  dst->export_loc = bfd_getb32 (src->export_loc);
1934
4.98k
  dst->export_count = bfd_getb32 (src->export_count);
1935
4.98k
  dst->import_loc = bfd_getb32 (src->import_loc);
1936
4.98k
  dst->aux_loc = bfd_getb32 (src->aux_loc);
1937
4.98k
  dst->aux_size = bfd_getb32 (src->aux_size);
1938
4.98k
  dst->string_loc = bfd_getb32 (src->string_loc);
1939
4.98k
  dst->string_size = bfd_getb32 (src->string_size);
1940
4.98k
  dst->free_list = bfd_getb32 (src->free_list);
1941
4.98k
  dst->file_end = bfd_getb32 (src->file_end);
1942
4.98k
  dst->checksum = bfd_getb32 (src->checksum);
1943
4.98k
}
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
16.0k
{
1954
16.0k
  asection *section;
1955
1956
  /* som_mkobject will set bfd_error if som_mkobject fails.  */
1957
16.0k
  if (! som_mkobject (abfd))
1958
0
    return NULL;
1959
1960
  /* Set BFD flags based on what information is available in the SOM.  */
1961
16.0k
  abfd->flags = BFD_NO_FLAGS;
1962
16.0k
  if (file_hdrp->symbol_total)
1963
13.0k
    abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
1964
1965
16.0k
  switch (file_hdrp->a_magic)
1966
16.0k
    {
1967
2.16k
    case DEMAND_MAGIC:
1968
2.16k
      abfd->flags |= (D_PAGED | WP_TEXT | EXEC_P);
1969
2.16k
      break;
1970
1.75k
    case SHARE_MAGIC:
1971
1.75k
      abfd->flags |= (WP_TEXT | EXEC_P);
1972
1.75k
      break;
1973
3.11k
    case EXEC_MAGIC:
1974
3.11k
      abfd->flags |= (EXEC_P);
1975
3.11k
      break;
1976
1.48k
    case RELOC_MAGIC:
1977
1.48k
      abfd->flags |= HAS_RELOC;
1978
1.48k
      break;
1979
0
#ifdef SHL_MAGIC
1980
672
    case SHL_MAGIC:
1981
672
#endif
1982
672
#ifdef DL_MAGIC
1983
7.28k
    case DL_MAGIC:
1984
7.28k
#endif
1985
7.28k
      abfd->flags |= DYNAMIC;
1986
7.28k
      break;
1987
1988
238
    default:
1989
238
      break;
1990
16.0k
    }
1991
1992
  /* Save the auxiliary header.  */
1993
16.0k
  obj_som_exec_hdr (abfd) = aux_hdrp;
1994
1995
  /* Allocate space to hold the saved exec header information.  */
1996
16.0k
  obj_som_exec_data (abfd) = bfd_zalloc (abfd, (bfd_size_type) sizeof (struct som_exec_data));
1997
16.0k
  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
16.0k
  if (aux_hdrp)
2016
11.2k
    {
2017
11.2k
      int found = 0;
2018
2019
46.6k
      for (section = abfd->sections; section; section = section->next)
2020
35.4k
  {
2021
35.4k
    bfd_vma entry;
2022
2023
35.4k
    if ((section->flags & SEC_CODE) == 0)
2024
27.9k
      continue;
2025
7.55k
    entry = aux_hdrp->exec_entry + aux_hdrp->exec_tmem;
2026
7.55k
    if (entry >= section->vma
2027
7.55k
        && entry < section->vma + section->size)
2028
1.18k
      found = 1;
2029
7.55k
  }
2030
11.2k
      if ((aux_hdrp->exec_entry == 0 && !(abfd->flags & DYNAMIC))
2031
11.2k
    || (aux_hdrp->exec_entry & 0x3) != 0
2032
11.2k
    || ! found)
2033
10.6k
  {
2034
10.6k
    abfd->start_address = aux_hdrp->exec_flags;
2035
10.6k
    obj_som_exec_data (abfd)->exec_flags = aux_hdrp->exec_entry;
2036
10.6k
  }
2037
555
      else
2038
555
  {
2039
555
    abfd->start_address = aux_hdrp->exec_entry + current_offset;
2040
555
    obj_som_exec_data (abfd)->exec_flags = aux_hdrp->exec_flags;
2041
555
  }
2042
11.2k
    }
2043
2044
16.0k
  obj_som_exec_data (abfd)->version_id = file_hdrp->version_id;
2045
2046
16.0k
  bfd_default_set_arch_mach (abfd, bfd_arch_hppa, pa10);
2047
16.0k
  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
16.0k
  obj_som_stringtab (abfd) = NULL;
2053
16.0k
  obj_som_symtab (abfd) = NULL;
2054
16.0k
  obj_som_sorted_syms (abfd) = NULL;
2055
16.0k
  obj_som_stringtab_size (abfd) = file_hdrp->symbol_strings_size;
2056
16.0k
  obj_som_sym_filepos (abfd) = file_hdrp->symbol_location + current_offset;
2057
16.0k
  obj_som_str_filepos (abfd) = (file_hdrp->symbol_strings_location
2058
16.0k
        + current_offset);
2059
16.0k
  obj_som_reloc_filepos (abfd) = (file_hdrp->fixup_request_location
2060
16.0k
          + current_offset);
2061
16.0k
  obj_som_exec_data (abfd)->system_id = file_hdrp->system_id;
2062
2063
16.0k
  return _bfd_no_cleanup;
2064
16.0k
}
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
31.0k
{
2077
31.0k
  char *space_strings = NULL;
2078
31.0k
  unsigned int space_index, i;
2079
31.0k
  unsigned int total_subspaces = 0;
2080
31.0k
  asection **subspace_sections = NULL;
2081
31.0k
  asection *section;
2082
31.0k
  size_t amt;
2083
2084
  /* First, read in space names.  */
2085
31.0k
  amt = file_hdr->space_strings_size;
2086
31.0k
  if (amt == (size_t) -1)
2087
0
    {
2088
0
      bfd_set_error (bfd_error_no_memory);
2089
0
      goto error_return;
2090
0
    }
2091
31.0k
  if (bfd_seek (abfd, current_offset + file_hdr->space_strings_location,
2092
31.0k
    SEEK_SET) != 0)
2093
0
    goto error_return;
2094
31.0k
  space_strings = (char *) _bfd_malloc_and_read (abfd, amt + 1, amt);
2095
31.0k
  if (space_strings == NULL)
2096
1.78k
    goto error_return;
2097
  /* Make sure that the string table is NUL terminated.  */
2098
29.2k
  space_strings[amt] = 0;
2099
2100
  /* Loop over all of the space dictionaries, building up sections.  */
2101
51.3k
  for (space_index = 0; space_index < file_hdr->space_total; space_index++)
2102
35.3k
    {
2103
35.3k
      struct som_space_dictionary_record space;
2104
35.3k
      struct som_external_space_dictionary_record ext_space;
2105
35.3k
      char *space_name;
2106
35.3k
      struct som_external_subspace_dictionary_record ext_subspace;
2107
35.3k
      struct som_subspace_dictionary_record subspace, save_subspace;
2108
35.3k
      unsigned int subspace_index;
2109
35.3k
      asection *space_asect;
2110
35.3k
      bfd_size_type space_size = 0;
2111
35.3k
      char *newname;
2112
2113
      /* Read the space dictionary element.  */
2114
35.3k
      if (bfd_seek (abfd,
2115
35.3k
        (current_offset + file_hdr->space_location
2116
35.3k
         + space_index * sizeof (ext_space)),
2117
35.3k
        SEEK_SET) != 0)
2118
0
  goto error_return;
2119
35.3k
      amt = sizeof ext_space;
2120
35.3k
      if (bfd_read (&ext_space, amt, abfd) != amt)
2121
2.10k
  goto error_return;
2122
2123
33.2k
      som_swap_space_dictionary_in (&ext_space, &space);
2124
2125
      /* Setup the space name string.  */
2126
33.2k
      if (space.name >= file_hdr->space_strings_size)
2127
1.00k
  goto error_return;
2128
2129
32.2k
      space_name = space.name + space_strings;
2130
2131
      /* Make a section out of it.  */
2132
32.2k
      amt = strlen (space_name) + 1;
2133
32.2k
      newname = bfd_alloc (abfd, amt);
2134
32.2k
      if (!newname)
2135
0
  goto error_return;
2136
32.2k
      strcpy (newname, space_name);
2137
2138
32.2k
      space_asect = bfd_make_section_anyway (abfd, newname);
2139
32.2k
      if (!space_asect)
2140
0
  goto error_return;
2141
2142
32.2k
      if (space.is_loadable == 0)
2143
27.9k
  space_asect->flags |= SEC_DEBUGGING;
2144
2145
      /* Set up all the attributes for the space.  */
2146
32.2k
      if (! bfd_som_set_section_attributes (space_asect, space.is_defined,
2147
32.2k
              space.is_private, space.sort_key,
2148
32.2k
              space.space_number))
2149
0
  goto error_return;
2150
2151
      /* If the space has no subspaces, then we're done.  */
2152
32.2k
      if (space.subspace_quantity == 0)
2153
11.1k
  continue;
2154
2155
      /* Now, read in the first subspace for this space.  */
2156
21.0k
      if (bfd_seek (abfd,
2157
21.0k
        (current_offset + file_hdr->subspace_location
2158
21.0k
         + space.subspace_index * sizeof ext_subspace),
2159
21.0k
        SEEK_SET) != 0)
2160
631
  goto error_return;
2161
20.4k
      amt = sizeof ext_subspace;
2162
20.4k
      if (bfd_read (&ext_subspace, amt, abfd) != amt)
2163
994
  goto error_return;
2164
      /* Seek back to the start of the subspaces for loop below.  */
2165
19.4k
      if (bfd_seek (abfd,
2166
19.4k
        (current_offset + file_hdr->subspace_location
2167
19.4k
         + space.subspace_index * sizeof ext_subspace),
2168
19.4k
        SEEK_SET) != 0)
2169
0
  goto error_return;
2170
2171
19.4k
      som_swap_subspace_dictionary_in (&ext_subspace, &subspace);
2172
2173
      /* Setup the start address and file loc from the first subspace
2174
   record.  */
2175
19.4k
      space_asect->vma = subspace.subspace_start;
2176
19.4k
      space_asect->filepos = subspace.file_loc_init_value + current_offset;
2177
19.4k
      space_asect->alignment_power = exact_log2 (subspace.alignment);
2178
19.4k
      if (space_asect->alignment_power == (unsigned) -1)
2179
2.08k
  goto error_return;
2180
2181
      /* Initialize save_subspace so we can reliably determine if this
2182
   loop placed any useful values into it.  */
2183
17.3k
      memset (&save_subspace, 0, sizeof (save_subspace));
2184
2185
      /* Loop over the rest of the subspaces, building up more sections.  */
2186
63.0k
      for (subspace_index = 0; subspace_index < space.subspace_quantity;
2187
45.7k
     subspace_index++)
2188
52.0k
  {
2189
52.0k
    asection *subspace_asect;
2190
52.0k
    char *subspace_name;
2191
2192
    /* Read in the next subspace.  */
2193
52.0k
    amt = sizeof ext_subspace;
2194
52.0k
    if (bfd_read (&ext_subspace, amt, abfd) != amt)
2195
2.19k
      goto error_return;
2196
2197
49.8k
    som_swap_subspace_dictionary_in (&ext_subspace, &subspace);
2198
2199
    /* Setup the subspace name string.  */
2200
49.8k
    if (subspace.name >= file_hdr->space_strings_size)
2201
1.99k
      goto error_return;
2202
2203
47.8k
    subspace_name = subspace.name + space_strings;
2204
2205
47.8k
    amt = strlen (subspace_name) + 1;
2206
47.8k
    newname = bfd_alloc (abfd, amt);
2207
47.8k
    if (!newname)
2208
0
      goto error_return;
2209
47.8k
    strcpy (newname, subspace_name);
2210
2211
    /* Make a section out of this subspace.  */
2212
47.8k
    subspace_asect = bfd_make_section_anyway (abfd, newname);
2213
47.8k
    if (!subspace_asect)
2214
0
      goto error_return;
2215
2216
    /* Store private information about the section.  */
2217
47.8k
    if (! bfd_som_set_subsection_attributes (subspace_asect, space_asect,
2218
47.8k
               subspace.access_control_bits,
2219
47.8k
               subspace.sort_key,
2220
47.8k
               subspace.quadrant,
2221
47.8k
               subspace.is_comdat,
2222
47.8k
               subspace.is_common,
2223
47.8k
               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
47.8k
    total_subspaces++;
2236
47.8k
    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
47.8k
    switch (subspace.access_control_bits >> 4)
2241
47.8k
      {
2242
      /* Readonly data.  */
2243
33.7k
      case 0x0:
2244
33.7k
        subspace_asect->flags |= SEC_DATA | SEC_READONLY;
2245
33.7k
        break;
2246
2247
      /* Normal data.  */
2248
2.46k
      case 0x1:
2249
2.46k
        subspace_asect->flags |= SEC_DATA;
2250
2.46k
        break;
2251
2252
      /* Readonly code and the gateways.
2253
         Gateways have other attributes which do not map
2254
         into anything BFD knows about.  */
2255
652
      case 0x2:
2256
3.08k
      case 0x4:
2257
3.52k
      case 0x5:
2258
3.93k
      case 0x6:
2259
8.58k
      case 0x7:
2260
8.58k
        subspace_asect->flags |= SEC_CODE | SEC_READONLY;
2261
8.58k
        break;
2262
2263
      /* dynamic (writable) code.  */
2264
3.07k
      case 0x3:
2265
3.07k
        subspace_asect->flags |= SEC_CODE;
2266
3.07k
        break;
2267
47.8k
      }
2268
2269
47.8k
    if (subspace.is_comdat || subspace.is_common || subspace.dup_common)
2270
25.4k
      subspace_asect->flags |= SEC_LINK_ONCE;
2271
2272
47.8k
    if (subspace.subspace_length > 0)
2273
33.2k
      subspace_asect->flags |= SEC_HAS_CONTENTS;
2274
2275
47.8k
    if (subspace.is_loadable)
2276
13.8k
      subspace_asect->flags |= SEC_ALLOC | SEC_LOAD;
2277
34.0k
    else
2278
34.0k
      subspace_asect->flags |= SEC_DEBUGGING;
2279
2280
47.8k
    if (subspace.code_only)
2281
11.6k
      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
47.8k
    if (subspace.file_loc_init_value == 0
2286
47.8k
        && subspace.initialization_length == 0)
2287
4.54k
      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
47.8k
    if (subspace.fixup_request_quantity != 0)
2294
37.0k
      {
2295
37.0k
        subspace_asect->flags |= SEC_RELOC;
2296
37.0k
        subspace_asect->rel_filepos = subspace.fixup_request_index;
2297
37.0k
        som_section_data (subspace_asect)->reloc_size
2298
37.0k
    = 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
37.0k
        subspace_asect->reloc_count = (unsigned) -1;
2302
37.0k
      }
2303
2304
    /* Update save_subspace if appropriate.  */
2305
47.8k
    if (subspace.file_loc_init_value > save_subspace.file_loc_init_value)
2306
17.4k
      save_subspace = subspace;
2307
2308
47.8k
    subspace_asect->vma = subspace.subspace_start;
2309
47.8k
    subspace_asect->size = subspace.subspace_length;
2310
47.8k
    subspace_asect->filepos = (subspace.file_loc_init_value
2311
47.8k
             + current_offset);
2312
47.8k
    subspace_asect->alignment_power = exact_log2 (subspace.alignment);
2313
47.8k
    if (subspace_asect->alignment_power == (unsigned) -1)
2314
2.16k
      goto error_return;
2315
2316
    /* Keep track of the accumulated sizes of the sections.  */
2317
45.7k
    space_size += subspace.subspace_length;
2318
45.7k
  }
2319
2320
      /* This can happen for a .o which defines symbols in otherwise
2321
   empty subspaces.  */
2322
11.0k
      if (!save_subspace.file_loc_init_value)
2323
1.24k
  space_asect->size = 0;
2324
9.75k
      else
2325
9.75k
  {
2326
9.75k
    if (file_hdr->a_magic != RELOC_MAGIC)
2327
7.81k
      {
2328
        /* Setup the size for the space section based upon the info
2329
     in the last subspace of the space.  */
2330
7.81k
        space_asect->size = (save_subspace.subspace_start
2331
7.81k
           - space_asect->vma
2332
7.81k
           + save_subspace.subspace_length);
2333
7.81k
      }
2334
1.94k
    else
2335
1.94k
      {
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
1.94k
        space_asect->size = space_size;
2342
1.94k
      }
2343
9.75k
  }
2344
11.0k
    }
2345
  /* Now that we've read in all the subspace records, we need to assign
2346
     a target index to each subspace.  */
2347
16.0k
  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
16.0k
  subspace_sections = bfd_malloc (amt);
2353
16.0k
  if (subspace_sections == NULL)
2354
0
    goto error_return;
2355
2356
51.9k
  for (i = 0, section = abfd->sections; section; section = section->next)
2357
35.8k
    {
2358
35.8k
      if (!som_is_subspace (section))
2359
12.8k
  continue;
2360
2361
23.0k
      subspace_sections[i] = section;
2362
23.0k
      i++;
2363
23.0k
    }
2364
16.0k
  qsort (subspace_sections, total_subspaces,
2365
16.0k
   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
39.1k
  for (i = 0; i < total_subspaces; i++)
2370
23.0k
    subspace_sections[i]->target_index = i;
2371
2372
16.0k
  free (space_strings);
2373
16.0k
  free (subspace_sections);
2374
16.0k
  return true;
2375
2376
14.9k
 error_return:
2377
14.9k
  free (space_strings);
2378
14.9k
  free (subspace_sections);
2379
14.9k
  return false;
2380
16.0k
}
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
3.41M
{
2388
3.41M
  struct som_external_header ext_file_hdr;
2389
3.41M
  struct som_header file_hdr;
2390
3.41M
  struct som_exec_auxhdr *aux_hdr_ptr = NULL;
2391
3.41M
  unsigned long current_offset = 0;
2392
3.41M
  struct som_external_lst_header ext_lst_header;
2393
3.41M
  struct som_external_som_entry ext_som_entry;
2394
3.41M
  size_t amt;
2395
3.41M
  unsigned int loc;
2396
3.41M
#define ENTRY_SIZE sizeof (struct som_external_som_entry)
2397
2398
3.41M
  amt = sizeof (struct som_external_header);
2399
3.41M
  if (bfd_read (&ext_file_hdr, amt, abfd) != amt)
2400
889k
    {
2401
889k
      if (bfd_get_error () != bfd_error_system_call)
2402
888k
  bfd_set_error (bfd_error_wrong_format);
2403
889k
      return NULL;
2404
889k
    }
2405
2406
2.52M
  som_swap_header_in (&ext_file_hdr, &file_hdr);
2407
2408
2.52M
  if (!_PA_RISC_ID (file_hdr.system_id))
2409
2.48M
    {
2410
2.48M
      bfd_set_error (bfd_error_wrong_format);
2411
2.48M
      return NULL;
2412
2.48M
    }
2413
2414
37.5k
  switch (file_hdr.a_magic)
2415
37.5k
    {
2416
2.22k
    case RELOC_MAGIC:
2417
7.27k
    case EXEC_MAGIC:
2418
17.7k
    case SHARE_MAGIC:
2419
20.7k
    case DEMAND_MAGIC:
2420
32.8k
    case DL_MAGIC:
2421
33.9k
    case SHL_MAGIC:
2422
#ifdef SHARED_MAGIC_CNX
2423
    case SHARED_MAGIC_CNX:
2424
#endif
2425
33.9k
      break;
2426
2427
1.27k
    case EXECLIBMAGIC:
2428
      /* Read the lst header and determine where the SOM directory begins.  */
2429
2430
1.27k
      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
1.27k
      amt = sizeof (struct som_external_lst_header);
2438
1.27k
      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
1.27k
      loc = bfd_getb32 (ext_lst_header.dir_loc);
2447
1.27k
      if (bfd_seek (abfd, loc, SEEK_SET) != 0)
2448
0
  {
2449
0
    if (bfd_get_error () != bfd_error_system_call)
2450
0
      bfd_set_error (bfd_error_wrong_format);
2451
0
    return NULL;
2452
0
  }
2453
2454
1.27k
      amt = ENTRY_SIZE;
2455
1.27k
      if (bfd_read (&ext_som_entry, amt, abfd) != amt)
2456
412
  {
2457
412
    if (bfd_get_error () != bfd_error_system_call)
2458
412
      bfd_set_error (bfd_error_wrong_format);
2459
412
    return NULL;
2460
412
  }
2461
2462
      /* Now position to the first SOM.  */
2463
859
      current_offset = bfd_getb32 (ext_som_entry.location);
2464
859
      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
859
      amt = sizeof (struct som_external_header);
2473
859
      if (bfd_read (&ext_file_hdr, amt, abfd) != amt)
2474
412
  {
2475
412
    if (bfd_get_error () != bfd_error_system_call)
2476
412
      bfd_set_error (bfd_error_wrong_format);
2477
412
    return NULL;
2478
412
  }
2479
2480
447
      som_swap_header_in (&ext_file_hdr, &file_hdr);
2481
2482
447
      break;
2483
2484
2.27k
    default:
2485
2.27k
      bfd_set_error (bfd_error_wrong_format);
2486
2.27k
      return NULL;
2487
37.5k
    }
2488
2489
34.4k
  if (file_hdr.version_id != OLD_VERSION_ID
2490
34.4k
      && file_hdr.version_id != NEW_VERSION_ID)
2491
1.58k
    {
2492
1.58k
      bfd_set_error (bfd_error_wrong_format);
2493
1.58k
      return NULL;
2494
1.58k
    }
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
32.8k
  if (file_hdr.aux_header_size != 0)
2500
25.7k
    {
2501
25.7k
      struct som_external_exec_auxhdr ext_exec_auxhdr;
2502
2503
25.7k
      aux_hdr_ptr = bfd_zalloc (abfd,
2504
25.7k
        (bfd_size_type) sizeof (*aux_hdr_ptr));
2505
25.7k
      if (aux_hdr_ptr == NULL)
2506
0
  return NULL;
2507
25.7k
      amt = sizeof (struct som_external_exec_auxhdr);
2508
25.7k
      if (bfd_read (&ext_exec_auxhdr, amt, abfd) != amt)
2509
1.81k
  {
2510
1.81k
    if (bfd_get_error () != bfd_error_system_call)
2511
1.81k
      bfd_set_error (bfd_error_wrong_format);
2512
1.81k
    return NULL;
2513
1.81k
  }
2514
23.9k
      som_swap_exec_auxhdr_in (&ext_exec_auxhdr, aux_hdr_ptr);
2515
23.9k
    }
2516
2517
31.0k
  if (!setup_sections (abfd, &file_hdr, current_offset))
2518
14.9k
    {
2519
      /* setup_sections does not bubble up a bfd error code.  */
2520
14.9k
      bfd_set_error (bfd_error_bad_value);
2521
14.9k
      return NULL;
2522
14.9k
    }
2523
2524
  /* This appears to be a valid SOM object.  Do some initialization.  */
2525
16.0k
  return som_object_setup (abfd, &file_hdr, aux_hdr_ptr, current_offset);
2526
31.0k
}
2527
2528
/* Create a SOM object.  */
2529
2530
static bool
2531
som_mkobject (bfd *abfd)
2532
16.0k
{
2533
  /* Allocate memory to hold backend information.  */
2534
16.0k
  abfd->tdata.som_data = bfd_zalloc (abfd, (bfd_size_type) sizeof (struct som_data_struct));
2535
16.0k
  if (abfd->tdata.som_data == NULL)
2536
0
    return false;
2537
16.0k
  return true;
2538
16.0k
}
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
0
{
2547
0
  struct som_header *file_hdr;
2548
0
  asection *section;
2549
0
  size_t amt = sizeof (struct som_header);
2550
2551
  /* Make and attach a file header to the BFD.  */
2552
0
  file_hdr = bfd_zalloc (abfd, amt);
2553
0
  if (file_hdr == NULL)
2554
0
    return false;
2555
0
  obj_som_file_hdr (abfd) = file_hdr;
2556
2557
0
  if (abfd->flags & (EXEC_P | DYNAMIC))
2558
0
    {
2559
      /* Make and attach an exec header to the BFD.  */
2560
0
      amt = sizeof (struct som_exec_auxhdr);
2561
0
      obj_som_exec_hdr (abfd) = bfd_zalloc (abfd, amt);
2562
0
      if (obj_som_exec_hdr (abfd) == NULL)
2563
0
  return false;
2564
2565
0
      if (abfd->flags & D_PAGED)
2566
0
  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
0
    }
2576
0
  else
2577
0
    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
0
  file_hdr->file_time.secs = 0;
2583
0
  file_hdr->file_time.nanosecs = 0;
2584
2585
0
  file_hdr->entry_space = 0;
2586
0
  file_hdr->entry_subspace = 0;
2587
0
  file_hdr->entry_offset = 0;
2588
0
  file_hdr->presumed_dp = 0;
2589
2590
  /* Now iterate over the sections translating information from
2591
     BFD sections to SOM spaces/subspaces.  */
2592
0
  for (section = abfd->sections; section != NULL; section = section->next)
2593
0
    {
2594
      /* Ignore anything which has not been marked as a space or
2595
   subspace.  */
2596
0
      if (!som_is_space (section) && !som_is_subspace (section))
2597
0
  continue;
2598
2599
0
      if (som_is_space (section))
2600
0
  {
2601
    /* Allocate space for the space dictionary.  */
2602
0
    amt = sizeof (struct som_space_dictionary_record);
2603
0
    som_section_data (section)->space_dict = bfd_zalloc (abfd, amt);
2604
0
    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
0
    som_section_data (section)->space_dict->loader_fix_index = -1;
2609
0
    som_section_data (section)->space_dict->init_pointer_index = -1;
2610
2611
    /* Set more attributes that were stuffed away in private data.  */
2612
0
    som_section_data (section)->space_dict->sort_key =
2613
0
      som_section_data (section)->copy_data->sort_key;
2614
0
    som_section_data (section)->space_dict->is_defined =
2615
0
      som_section_data (section)->copy_data->is_defined;
2616
0
    som_section_data (section)->space_dict->is_private =
2617
0
      som_section_data (section)->copy_data->is_private;
2618
0
    som_section_data (section)->space_dict->space_number =
2619
0
      som_section_data (section)->copy_data->space_number;
2620
0
  }
2621
0
      else
2622
0
  {
2623
    /* Allocate space for the subspace dictionary.  */
2624
0
    amt = sizeof (struct som_subspace_dictionary_record);
2625
0
    som_section_data (section)->subspace_dict = bfd_zalloc (abfd, amt);
2626
0
    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
0
    if (section->flags & SEC_ALLOC)
2633
0
      som_section_data (section)->subspace_dict->is_loadable = 1;
2634
2635
0
    if (section->flags & SEC_CODE)
2636
0
      som_section_data (section)->subspace_dict->code_only = 1;
2637
2638
0
    som_section_data (section)->subspace_dict->subspace_start =
2639
0
      section->vma;
2640
0
    som_section_data (section)->subspace_dict->subspace_length =
2641
0
      section->size;
2642
0
    som_section_data (section)->subspace_dict->initialization_length =
2643
0
      section->size;
2644
0
    som_section_data (section)->subspace_dict->alignment =
2645
0
      1 << section->alignment_power;
2646
2647
    /* Set more attributes that were stuffed away in private data.  */
2648
0
    som_section_data (section)->subspace_dict->sort_key =
2649
0
      som_section_data (section)->copy_data->sort_key;
2650
0
    som_section_data (section)->subspace_dict->access_control_bits =
2651
0
      som_section_data (section)->copy_data->access_control_bits;
2652
0
    som_section_data (section)->subspace_dict->quadrant =
2653
0
      som_section_data (section)->copy_data->quadrant;
2654
0
    som_section_data (section)->subspace_dict->is_comdat =
2655
0
      som_section_data (section)->copy_data->is_comdat;
2656
0
    som_section_data (section)->subspace_dict->is_common =
2657
0
      som_section_data (section)->copy_data->is_common;
2658
0
    som_section_data (section)->subspace_dict->dup_common =
2659
0
      som_section_data (section)->copy_data->dup_common;
2660
0
  }
2661
0
    }
2662
0
  return true;
2663
0
}
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
0
{
2670
  /* If no copy data is available, then it's neither a space nor a
2671
     subspace.  */
2672
0
  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
0
  if (som_section_data (section)->copy_data->container != section
2678
0
      && (som_section_data (section)->copy_data->container->output_section
2679
0
    != section))
2680
0
    return false;
2681
2682
  /* OK.  Must be a space.  */
2683
0
  return true;
2684
0
}
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
36.5k
{
2691
  /* If no copy data is available, then it's neither a space nor a
2692
     subspace.  */
2693
36.5k
  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
36.5k
  if (som_section_data (section)->copy_data->container == section
2699
36.5k
      || (som_section_data (section)->copy_data->container->output_section
2700
23.1k
    == section))
2701
13.4k
    return false;
2702
2703
  /* OK.  Must be a subspace.  */
2704
23.1k
  return true;
2705
36.5k
}
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
0
{
2714
0
  return (som_section_data (subspace)->copy_data->container == space)
2715
0
    || (som_section_data (subspace)->copy_data->container->output_section
2716
0
  == space);
2717
0
}
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
0
{
2724
0
  int count = 0;
2725
0
  asection *section;
2726
2727
0
  for (section = abfd->sections; section != NULL; section = section->next)
2728
0
    count += som_is_space (section);
2729
2730
0
  return count;
2731
0
}
2732
2733
/* Count the number of subspaces attached to the given BFD.  */
2734
2735
static unsigned long
2736
som_count_subspaces (bfd *abfd)
2737
0
{
2738
0
  int count = 0;
2739
0
  asection *section;
2740
2741
0
  for (section = abfd->sections; section != NULL; section = section->next)
2742
0
    count += som_is_subspace (section);
2743
2744
0
  return count;
2745
0
}
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
0
{
2756
0
  asymbol **sym1 = (asymbol **) arg1;
2757
0
  asymbol **sym2 = (asymbol **) arg2;
2758
0
  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
0
  if ((*sym1)->flags & BSF_SECTION_SYM)
2763
0
    count1 = (*sym1)->udata.i;
2764
0
  else
2765
0
    count1 = som_symbol_data (*sym1)->reloc_count;
2766
2767
0
  if ((*sym2)->flags & BSF_SECTION_SYM)
2768
0
    count2 = (*sym2)->udata.i;
2769
0
  else
2770
0
    count2 = som_symbol_data (*sym2)->reloc_count;
2771
2772
  /* Return the appropriate value.  */
2773
0
  if (count1 < count2)
2774
0
    return 1;
2775
0
  else if (count1 > count2)
2776
0
    return -1;
2777
0
  return 0;
2778
0
}
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
51.5k
{
2786
51.5k
  asection **subspace1 = (asection **) arg1;
2787
51.5k
  asection **subspace2 = (asection **) arg2;
2788
2789
51.5k
  if ((*subspace1)->target_index < (*subspace2)->target_index)
2790
19.9k
    return -1;
2791
31.5k
  else if ((*subspace2)->target_index < (*subspace1)->target_index)
2792
15.2k
    return 1;
2793
16.3k
  else
2794
16.3k
    return 0;
2795
51.5k
}
2796
2797
/* Perform various work in preparation for emitting the fixup stream.  */
2798
2799
static bool
2800
som_prep_for_fixups (bfd *abfd, asymbol **syms, unsigned long num_syms)
2801
0
{
2802
0
  unsigned long i;
2803
0
  asection *section;
2804
0
  asymbol **sorted_syms;
2805
0
  size_t amt;
2806
2807
0
  if (num_syms == 0)
2808
0
    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
0
  for (i = 0; i < num_syms; i++)
2816
0
    {
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
0
      if (som_symbol_data (syms[i]) == NULL
2821
0
    || 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
0
      else
2827
0
  som_symbol_data (syms[i])->reloc_count = 0;
2828
0
    }
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
0
  for (section = abfd->sections; section != NULL; section = section->next)
2833
0
    {
2834
0
      int j;
2835
2836
      /* Does this section have any relocations?  */
2837
0
      if ((int) section->reloc_count <= 0)
2838
0
  continue;
2839
2840
      /* Walk through each relocation for this section.  */
2841
0
      for (j = 1; j < (int) section->reloc_count; j++)
2842
0
  {
2843
0
    arelent *reloc = section->orelocation[j];
2844
0
    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
0
    if (reloc->sym_ptr_ptr == NULL
2850
0
        || bfd_is_abs_section ((*reloc->sym_ptr_ptr)->section))
2851
0
      continue;
2852
2853
    /* Scaling to encourage symbols involved in R_DP_RELATIVE
2854
       and R_CODE_ONE_SYMBOL relocations to come first.  These
2855
       two relocations have single byte versions if the symbol
2856
       index is very small.  */
2857
0
    if (reloc->howto->type == R_DP_RELATIVE
2858
0
        || reloc->howto->type == R_CODE_ONE_SYMBOL)
2859
0
      scale = 2;
2860
0
    else
2861
0
      scale = 1;
2862
2863
    /* Handle section symbols by storing the count in the udata
2864
       field.  It will not be used and the count is very important
2865
       for these symbols.  */
2866
0
    if ((*reloc->sym_ptr_ptr)->flags & BSF_SECTION_SYM)
2867
0
      {
2868
0
        (*reloc->sym_ptr_ptr)->udata.i =
2869
0
    (*reloc->sym_ptr_ptr)->udata.i + scale;
2870
0
        continue;
2871
0
      }
2872
2873
    /* A normal symbol.  Increment the count.  */
2874
0
    som_symbol_data (*reloc->sym_ptr_ptr)->reloc_count += scale;
2875
0
  }
2876
0
    }
2877
2878
  /* Sort a copy of the symbol table, rather than the canonical
2879
     output symbol table.  */
2880
0
  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
0
  sorted_syms = bfd_zalloc (abfd, amt);
2886
0
  if (sorted_syms == NULL)
2887
0
    return false;
2888
0
  memcpy (sorted_syms, syms, num_syms * sizeof (asymbol *));
2889
0
  qsort (sorted_syms, num_syms, sizeof (asymbol *), compare_syms);
2890
0
  obj_som_sorted_syms (abfd) = sorted_syms;
2891
2892
  /* Compute the symbol indexes, they will be needed by the relocation
2893
     code.  */
2894
0
  for (i = 0; i < num_syms; i++)
2895
0
    {
2896
      /* A section symbol.  Again, there is no pointer to backend symbol
2897
   information, so we reuse the udata field again.  */
2898
0
      if (sorted_syms[i]->flags & BSF_SECTION_SYM)
2899
0
  sorted_syms[i]->udata.i = i;
2900
0
      else
2901
0
  som_symbol_data (sorted_syms[i])->index = i;
2902
0
    }
2903
0
  return true;
2904
0
}
2905
2906
static bool
2907
som_write_fixups (bfd *abfd,
2908
      unsigned long current_offset,
2909
      unsigned int *total_reloc_sizep)
2910
0
{
2911
0
  unsigned int i, j;
2912
  /* Chunk of memory that we can use as buffer space, then throw
2913
     away.  */
2914
0
  unsigned char tmp_space[SOM_TMP_BUFSIZE];
2915
0
  unsigned char *p;
2916
0
  unsigned int total_reloc_size = 0;
2917
0
  unsigned int subspace_reloc_size = 0;
2918
0
  unsigned int num_spaces = obj_som_file_hdr (abfd)->space_total;
2919
0
  asection *section = abfd->sections;
2920
0
  size_t amt;
2921
2922
0
  memset (tmp_space, 0, SOM_TMP_BUFSIZE);
2923
0
  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
0
  for (i = 0; i < num_spaces; i++)
2933
0
    {
2934
0
      asection *subsection;
2935
2936
      /* Find a space.  */
2937
0
      while (section && !som_is_space (section))
2938
0
  section = section->next;
2939
0
      if (!section)
2940
0
  break;
2941
2942
      /* Now iterate through each of its subspaces.  */
2943
0
      for (subsection = abfd->sections;
2944
0
     subsection != NULL;
2945
0
     subsection = subsection->next)
2946
0
  {
2947
0
    unsigned int reloc_offset;
2948
0
    unsigned int current_rounding_mode;
2949
0
#ifndef NO_PCREL_MODES
2950
0
    unsigned int current_call_mode;
2951
0
#endif
2952
2953
    /* Find a subspace of this space.  */
2954
0
    if (!som_is_subspace (subsection)
2955
0
        || !som_is_container (section, subsection))
2956
0
      continue;
2957
2958
    /* If this subspace does not have real data, then we are
2959
       finished with it.  */
2960
0
    if ((subsection->flags & SEC_HAS_CONTENTS) == 0)
2961
0
      {
2962
0
        som_section_data (subsection)->subspace_dict->fixup_request_index
2963
0
    = -1;
2964
0
        continue;
2965
0
      }
2966
2967
    /* This subspace has some relocations.  Put the relocation stream
2968
       index into the subspace record.  */
2969
0
    som_section_data (subsection)->subspace_dict->fixup_request_index
2970
0
      = 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
0
    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
0
    p = tmp_space;
2982
0
    subspace_reloc_size = 0;
2983
0
    reloc_offset = 0;
2984
0
    som_initialize_reloc_queue (reloc_queue);
2985
0
    current_rounding_mode = R_N_MODE;
2986
0
#ifndef NO_PCREL_MODES
2987
0
    current_call_mode = R_SHORT_PCREL_MODE;
2988
0
#endif
2989
2990
    /* Translate each BFD relocation into one or more SOM
2991
       relocations.  */
2992
0
    for (j = 0; j < subsection->reloc_count; j++)
2993
0
      {
2994
0
        arelent *bfd_reloc = subsection->orelocation[j];
2995
0
        unsigned int skip;
2996
0
        int sym_num;
2997
2998
0
        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
0
        if (!bfd_reloc_offset_in_range (bfd_reloc->howto,
3010
0
                abfd, subsection,
3011
0
                bfd_reloc->address))
3012
0
    {
3013
0
      _bfd_error_handler
3014
        /* xgettext:c-format */
3015
0
        (_("%pB(%pA+%#" PRIx64 "): "
3016
0
           "%s relocation offset out of range"),
3017
0
         abfd, subsection, (uint64_t) bfd_reloc->address,
3018
0
         bfd_reloc->howto->name);
3019
0
      bfd_set_error (bfd_error_bad_value);
3020
0
      return false;
3021
0
    }
3022
3023
        /* Get the symbol number.  Remember it's stored in a
3024
     special place for section symbols.  */
3025
0
        if ((*bfd_reloc->sym_ptr_ptr)->flags & BSF_SECTION_SYM)
3026
0
    sym_num = (*bfd_reloc->sym_ptr_ptr)->udata.i;
3027
0
        else
3028
0
    sym_num = som_symbol_data (*bfd_reloc->sym_ptr_ptr)->index;
3029
3030
        /* If there is not enough room for the next couple relocations,
3031
     then dump the current buffer contents now.  Also reinitialize
3032
     the relocation queue.
3033
3034
     A single BFD relocation would probably only ever
3035
     translate into at most 20 bytes of SOM relocations.
3036
     However with fuzzed object files and resulting silly
3037
     values for "skip" below, som_reloc_skip can emit 262
3038
     bytes.  Leave lots of space for growth.  */
3039
0
        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
0
        skip = bfd_reloc->address - reloc_offset;
3052
0
        p = som_reloc_skip (abfd, skip, p,
3053
0
          &subspace_reloc_size, reloc_queue);
3054
3055
        /* Update reloc_offset for the next iteration.  */
3056
0
        reloc_offset = bfd_reloc->address + bfd_reloc->howto->size;
3057
3058
        /* Now the actual relocation we care about.  */
3059
0
        switch (bfd_reloc->howto->type)
3060
0
    {
3061
0
    case R_PCREL_CALL:
3062
0
    case R_ABS_CALL:
3063
0
      p = som_reloc_call (abfd, p, &subspace_reloc_size,
3064
0
              bfd_reloc, sym_num, reloc_queue);
3065
0
      break;
3066
3067
0
    case R_CODE_ONE_SYMBOL:
3068
0
    case R_DP_RELATIVE:
3069
      /* Account for any addend.  */
3070
0
      if (bfd_reloc->addend)
3071
0
        p = som_reloc_addend (abfd, bfd_reloc->addend, p,
3072
0
            &subspace_reloc_size, reloc_queue);
3073
3074
0
      if (sym_num < 0x20)
3075
0
        {
3076
0
          bfd_put_8 (abfd, bfd_reloc->howto->type + sym_num, p);
3077
0
          subspace_reloc_size += 1;
3078
0
          p += 1;
3079
0
        }
3080
0
      else if (sym_num < 0x100)
3081
0
        {
3082
0
          bfd_put_8 (abfd, bfd_reloc->howto->type + 32, p);
3083
0
          bfd_put_8 (abfd, sym_num, p + 1);
3084
0
          p = try_prev_fixup (abfd, &subspace_reloc_size, p,
3085
0
            2, reloc_queue);
3086
0
        }
3087
0
      else if (sym_num < 0x10000000)
3088
0
        {
3089
0
          bfd_put_8 (abfd, bfd_reloc->howto->type + 33, p);
3090
0
          bfd_put_8 (abfd, sym_num >> 16, p + 1);
3091
0
          bfd_put_16 (abfd, (bfd_vma) sym_num, p + 2);
3092
0
          p = try_prev_fixup (abfd, &subspace_reloc_size,
3093
0
            p, 4, reloc_queue);
3094
0
        }
3095
0
      else
3096
0
        abort ();
3097
0
      break;
3098
3099
0
    case R_DATA_GPREL:
3100
      /* Account for any addend.  */
3101
0
      if (bfd_reloc->addend)
3102
0
        p = som_reloc_addend (abfd, bfd_reloc->addend, p,
3103
0
            &subspace_reloc_size, reloc_queue);
3104
3105
0
      if (sym_num < 0x10000000)
3106
0
        {
3107
0
          bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3108
0
          bfd_put_8 (abfd, sym_num >> 16, p + 1);
3109
0
          bfd_put_16 (abfd, (bfd_vma) sym_num, p + 2);
3110
0
          p = try_prev_fixup (abfd, &subspace_reloc_size,
3111
0
            p, 4, reloc_queue);
3112
0
        }
3113
0
      else
3114
0
        abort ();
3115
0
      break;
3116
3117
0
    case R_DATA_ONE_SYMBOL:
3118
0
    case R_DATA_PLABEL:
3119
0
    case R_CODE_PLABEL:
3120
0
    case R_DLT_REL:
3121
      /* Account for any addend using R_DATA_OVERRIDE.  */
3122
0
      if (bfd_reloc->howto->type != R_DATA_ONE_SYMBOL
3123
0
          && bfd_reloc->addend)
3124
0
        p = som_reloc_addend (abfd, bfd_reloc->addend, p,
3125
0
            &subspace_reloc_size, reloc_queue);
3126
3127
0
      if (sym_num < 0x100)
3128
0
        {
3129
0
          bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3130
0
          bfd_put_8 (abfd, sym_num, p + 1);
3131
0
          p = try_prev_fixup (abfd, &subspace_reloc_size, p,
3132
0
            2, reloc_queue);
3133
0
        }
3134
0
      else if (sym_num < 0x10000000)
3135
0
        {
3136
0
          bfd_put_8 (abfd, bfd_reloc->howto->type + 1, p);
3137
0
          bfd_put_8 (abfd, sym_num >> 16, p + 1);
3138
0
          bfd_put_16 (abfd, (bfd_vma) sym_num, p + 2);
3139
0
          p = try_prev_fixup (abfd, &subspace_reloc_size,
3140
0
            p, 4, reloc_queue);
3141
0
        }
3142
0
      else
3143
0
        abort ();
3144
0
      break;
3145
3146
0
    case R_ENTRY:
3147
0
      {
3148
0
        unsigned int tmp;
3149
0
        arelent *tmp_reloc = NULL;
3150
0
        bfd_put_8 (abfd, R_ENTRY, p);
3151
3152
        /* R_ENTRY relocations have 64 bits of associated
3153
           data.  Unfortunately the addend field of a bfd
3154
           relocation is only 32 bits.  So, we split up
3155
           the 64bit unwind information and store part in
3156
           the R_ENTRY relocation, and the rest in the R_EXIT
3157
           relocation.  */
3158
0
        bfd_put_32 (abfd, bfd_reloc->addend, p + 1);
3159
3160
        /* Find the next R_EXIT relocation.  */
3161
0
        for (tmp = j; tmp < subsection->reloc_count; tmp++)
3162
0
          {
3163
0
      tmp_reloc = subsection->orelocation[tmp];
3164
0
      if (tmp_reloc->howto->type == R_EXIT)
3165
0
        break;
3166
0
          }
3167
3168
0
        if (tmp == subsection->reloc_count)
3169
0
          abort ();
3170
3171
0
        bfd_put_32 (abfd, tmp_reloc->addend, p + 5);
3172
0
        p = try_prev_fixup (abfd, &subspace_reloc_size,
3173
0
          p, 9, reloc_queue);
3174
0
        break;
3175
0
      }
3176
3177
0
    case R_N_MODE:
3178
0
    case R_S_MODE:
3179
0
    case R_D_MODE:
3180
0
    case R_R_MODE:
3181
      /* If this relocation requests the current rounding
3182
         mode, then it is redundant.  */
3183
0
      if (bfd_reloc->howto->type != current_rounding_mode)
3184
0
        {
3185
0
          bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3186
0
          subspace_reloc_size += 1;
3187
0
          p += 1;
3188
0
          current_rounding_mode = bfd_reloc->howto->type;
3189
0
        }
3190
0
      break;
3191
3192
0
#ifndef NO_PCREL_MODES
3193
0
    case R_LONG_PCREL_MODE:
3194
0
    case R_SHORT_PCREL_MODE:
3195
0
      if (bfd_reloc->howto->type != current_call_mode)
3196
0
        {
3197
0
          bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3198
0
          subspace_reloc_size += 1;
3199
0
          p += 1;
3200
0
          current_call_mode = bfd_reloc->howto->type;
3201
0
        }
3202
0
      break;
3203
0
#endif
3204
3205
0
    case R_EXIT:
3206
0
    case R_ALT_ENTRY:
3207
0
    case R_FSEL:
3208
0
    case R_LSEL:
3209
0
    case R_RSEL:
3210
0
    case R_BEGIN_BRTAB:
3211
0
    case R_END_BRTAB:
3212
0
    case R_BEGIN_TRY:
3213
0
    case R_N0SEL:
3214
0
    case R_N1SEL:
3215
0
      bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3216
0
      subspace_reloc_size += 1;
3217
0
      p += 1;
3218
0
      break;
3219
3220
0
    case R_END_TRY:
3221
      /* The end of an exception handling region.  The reloc's
3222
         addend contains the offset of the exception handling
3223
         code.  */
3224
0
      if (bfd_reloc->addend == 0)
3225
0
        bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3226
0
      else if (bfd_reloc->addend < 1024)
3227
0
        {
3228
0
          bfd_put_8 (abfd, bfd_reloc->howto->type + 1, p);
3229
0
          bfd_put_8 (abfd, bfd_reloc->addend / 4, p + 1);
3230
0
          p = try_prev_fixup (abfd, &subspace_reloc_size,
3231
0
            p, 2, reloc_queue);
3232
0
        }
3233
0
      else
3234
0
        {
3235
0
          bfd_put_8 (abfd, bfd_reloc->howto->type + 2, p);
3236
0
          bfd_put_8 (abfd, (bfd_reloc->addend / 4) >> 16, p + 1);
3237
0
          bfd_put_16 (abfd, bfd_reloc->addend / 4, p + 2);
3238
0
          p = try_prev_fixup (abfd, &subspace_reloc_size,
3239
0
            p, 4, reloc_queue);
3240
0
        }
3241
0
      break;
3242
3243
0
    case R_COMP1:
3244
      /* The only time we generate R_COMP1, R_COMP2 and
3245
         R_CODE_EXPR relocs is for the difference of two
3246
         symbols.  Hence we can cheat here.  */
3247
0
      bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3248
0
      bfd_put_8 (abfd, 0x44, p + 1);
3249
0
      p = try_prev_fixup (abfd, &subspace_reloc_size,
3250
0
              p, 2, reloc_queue);
3251
0
      break;
3252
3253
0
    case R_COMP2:
3254
      /* The only time we generate R_COMP1, R_COMP2 and
3255
         R_CODE_EXPR relocs is for the difference of two
3256
         symbols.  Hence we can cheat here.  */
3257
0
      bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3258
0
      bfd_put_8 (abfd, 0x80, p + 1);
3259
0
      bfd_put_8 (abfd, sym_num >> 16, p + 2);
3260
0
      bfd_put_16 (abfd, (bfd_vma) sym_num, p + 3);
3261
0
      p = try_prev_fixup (abfd, &subspace_reloc_size,
3262
0
              p, 5, reloc_queue);
3263
0
      break;
3264
3265
0
    case R_CODE_EXPR:
3266
0
    case R_DATA_EXPR:
3267
      /* The only time we generate R_COMP1, R_COMP2 and
3268
         R_CODE_EXPR relocs is for the difference of two
3269
         symbols.  Hence we can cheat here.  */
3270
0
      bfd_put_8 (abfd, bfd_reloc->howto->type, p);
3271
0
      subspace_reloc_size += 1;
3272
0
      p += 1;
3273
0
      break;
3274
3275
    /* Put a "R_RESERVED" relocation in the stream if
3276
       we hit something we do not understand.  The linker
3277
       will complain loudly if this ever happens.  */
3278
0
    default:
3279
0
      bfd_put_8 (abfd, 0xff, p);
3280
0
      subspace_reloc_size += 1;
3281
0
      p += 1;
3282
0
      break;
3283
0
    }
3284
0
      }
3285
3286
    /* Last BFD relocation for a subspace has been processed.
3287
       Map the rest of the subspace with R_NO_RELOCATION fixups.  */
3288
0
    p = som_reloc_skip (abfd, subsection->size - reloc_offset,
3289
0
            p, &subspace_reloc_size, reloc_queue);
3290
3291
    /* Scribble out the relocations.  */
3292
0
    amt = p - tmp_space;
3293
0
    if (bfd_write (tmp_space, amt, abfd) != amt)
3294
0
      return false;
3295
0
    p = tmp_space;
3296
3297
0
    total_reloc_size += subspace_reloc_size;
3298
0
    som_section_data (subsection)->subspace_dict->fixup_request_quantity
3299
0
      = subspace_reloc_size;
3300
0
  }
3301
0
      section = section->next;
3302
0
    }
3303
0
  *total_reloc_sizep = total_reloc_size;
3304
0
  return true;
3305
0
}
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
0
{
3317
0
  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
0
  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
0
  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
0
  bfd_put_32 (abfd, length - 1, p);
3356
0
  *strings_size += 4;
3357
0
  p += 4;
3358
3359
0
  *strx = *strings_size;
3360
3361
  /* Next comes the string itself + a null terminator.  */
3362
0
  memcpy (p, str, length);
3363
0
  p += length;
3364
0
  *strings_size += length;
3365
3366
  /* Always align up to the next word boundary.  */
3367
0
  if (length & 3)
3368
0
    {
3369
0
      length = 4 - (length & 3);
3370
0
      memset (p, 0, length);
3371
0
      *strings_size += length;
3372
0
      p += length;
3373
0
    }
3374
0
  return p;
3375
0
}
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
0
{
3384
  /* Chunk of memory that we can use as buffer space, then throw
3385
     away.  */
3386
0
  size_t tmp_space_size = SOM_TMP_BUFSIZE;
3387
0
  char *tmp_space = bfd_malloc (tmp_space_size);
3388
0
  char *p = tmp_space;
3389
0
  asection *section;
3390
3391
0
  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
0
  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
0
  *strings_size = 0;
3402
0
  for (section = abfd->sections; section != NULL; section = section->next)
3403
0
    {
3404
0
      unsigned int *strx;
3405
3406
      /* Only work with space/subspaces; avoid any other sections
3407
   which might have been made (.text for example).  */
3408
0
      if (som_is_space (section))
3409
0
  strx = &som_section_data (section)->space_dict->name;
3410
0
      else if (som_is_subspace (section))
3411
0
  strx = &som_section_data (section)->subspace_dict->name;
3412
0
      else
3413
0
  continue;
3414
3415
0
      p = add_string (p, section->name, abfd, &tmp_space, &tmp_space_size,
3416
0
          strings_size, strx);
3417
0
      if (p == NULL)
3418
0
  return false;
3419
0
    }
3420
3421
  /* Done with the space/subspace strings.  Write out any information
3422
     contained in a partial block.  */
3423
0
  size_t amt = p - tmp_space;
3424
0
  bool ok = amt ? bfd_write (tmp_space, amt, abfd) == amt : true;
3425
0
  free (tmp_space);
3426
0
  return ok;
3427
0
}
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
0
{
3439
0
  unsigned int i;
3440
  /* Chunk of memory that we can use as buffer space, then throw
3441
     away.  */
3442
0
  size_t tmp_space_size = SOM_TMP_BUFSIZE;
3443
0
  char *tmp_space = bfd_malloc (tmp_space_size);
3444
0
  char *p = tmp_space;
3445
3446
0
  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
0
  if (bfd_seek (abfd, current_offset, SEEK_SET) != 0)
3459
0
    return false;
3460
3461
0
  *strings_size = 0;
3462
0
  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
0
  for (i = 0; i < num_syms; i++)
3495
0
    {
3496
0
      p = add_string (p, syms[i]->name, abfd, &tmp_space, &tmp_space_size,
3497
0
          strings_size,
3498
0
          &som_symbol_data (syms[i])->stringtab_offset);
3499
0
      if (p == NULL)
3500
0
  return false;
3501
0
    }
3502
3503
  /* Scribble out any partial block.  */
3504
0
  size_t amt = p - tmp_space;
3505
0
  bool ok = amt ? bfd_write (tmp_space, amt, abfd) == amt : true;
3506
0
  free (tmp_space);
3507
0
  return ok;
3508
0
}
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
0
{
3517
0
  unsigned long current_offset = 0;
3518
0
  unsigned int strings_size = 0;
3519
0
  unsigned long num_spaces, num_subspaces, i;
3520
0
  asection *section;
3521
0
  unsigned int total_subspaces = 0;
3522
0
  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
0
  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
0
  obj_som_file_hdr (abfd)->aux_header_location = current_offset;
3541
0
  obj_som_file_hdr (abfd)->aux_header_size = 0;
3542
0
  if (abfd->flags & (EXEC_P | DYNAMIC))
3543
0
    {
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
0
      current_offset += sizeof (struct som_external_exec_auxhdr);
3548
0
      obj_som_file_hdr (abfd)->aux_header_size
3549
0
  += sizeof (struct som_external_exec_auxhdr);
3550
0
      exec_header = obj_som_exec_hdr (abfd);
3551
0
      exec_header->som_auxhdr.type = EXEC_AUX_ID;
3552
0
      exec_header->som_auxhdr.length = 40;
3553
0
    }
3554
0
  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
0
  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
0
  obj_som_file_hdr (abfd)->init_array_location = current_offset;
3607
0
  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
0
  num_spaces = som_count_spaces (abfd);
3619
0
  obj_som_file_hdr (abfd)->space_location = current_offset;
3620
0
  obj_som_file_hdr (abfd)->space_total = num_spaces;
3621
0
  current_offset +=
3622
0
    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
0
  num_subspaces = som_count_subspaces (abfd);
3632
0
  obj_som_file_hdr (abfd)->subspace_location = current_offset;
3633
0
  obj_som_file_hdr (abfd)->subspace_total = num_subspaces;
3634
0
  current_offset
3635
0
    += 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
0
  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
0
  obj_som_file_hdr (abfd)->space_strings_location = current_offset;
3648
3649
  /* Scribble out the space strings.  */
3650
0
  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
0
  obj_som_file_hdr (abfd)->space_strings_size = strings_size;
3656
0
  current_offset += strings_size;
3657
3658
  /* Next is the compilation unit.  */
3659
0
  obj_som_file_hdr (abfd)->compiler_location = current_offset;
3660
0
  obj_som_file_hdr (abfd)->compiler_total = 0;
3661
0
  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
0
  section = abfd->sections;
3671
0
  for (i = 0; i < num_spaces; i++)
3672
0
    {
3673
0
      asection *subsection;
3674
0
      int first_subspace;
3675
0
      unsigned int subspace_offset = 0;
3676
3677
      /* Find a space.  */
3678
0
      while (!som_is_space (section))
3679
0
  section = section->next;
3680
3681
0
      first_subspace = 1;
3682
      /* Now look for all its subspaces.  */
3683
0
      for (subsection = abfd->sections;
3684
0
     subsection != NULL;
3685
0
     subsection = subsection->next)
3686
0
  {
3687
3688
0
    if (!som_is_subspace (subsection)
3689
0
        || !som_is_container (section, subsection)
3690
0
        || (subsection->flags & SEC_ALLOC) == 0)
3691
0
      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
0
    if (first_subspace
3697
0
        && (abfd->flags & (EXEC_P | DYNAMIC)))
3698
0
      {
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
0
        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
0
    current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
3711
3712
        /* Update the exec header.  */
3713
0
        if (subsection->flags & SEC_CODE && exec_header->exec_tfile == 0)
3714
0
    {
3715
0
      exec_header->exec_tmem = section->vma;
3716
0
      exec_header->exec_tfile = current_offset;
3717
0
    }
3718
0
        if (subsection->flags & SEC_DATA && exec_header->exec_dfile == 0)
3719
0
    {
3720
0
      exec_header->exec_dmem = section->vma;
3721
0
      exec_header->exec_dfile = current_offset;
3722
0
    }
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
0
        subspace_offset = subsection->vma;
3729
3730
        /* Only do this for the first subspace within each space.  */
3731
0
        first_subspace = 0;
3732
0
      }
3733
0
    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
0
    subsection->target_index = total_subspaces++;
3756
    /* This is real data to be loaded from the file.  */
3757
0
    if (subsection->flags & SEC_LOAD)
3758
0
      {
3759
        /* Update the size of the code & data.  */
3760
0
        if (abfd->flags & (EXEC_P | DYNAMIC)
3761
0
      && subsection->flags & SEC_CODE)
3762
0
    exec_header->exec_tsize += subsection->size;
3763
0
        else if (abfd->flags & (EXEC_P | DYNAMIC)
3764
0
           && subsection->flags & SEC_DATA)
3765
0
    exec_header->exec_dsize += subsection->size;
3766
0
        som_section_data (subsection)->subspace_dict->file_loc_init_value
3767
0
    = current_offset;
3768
0
        subsection->filepos = current_offset;
3769
0
        current_offset += subsection->size;
3770
0
        subspace_offset += subsection->size;
3771
0
      }
3772
    /* Looks like uninitialized data.  */
3773
0
    else
3774
0
      {
3775
        /* Update the size of the bss section.  */
3776
0
        if (abfd->flags & (EXEC_P | DYNAMIC))
3777
0
    exec_header->exec_bsize += subsection->size;
3778
3779
0
        som_section_data (subsection)->subspace_dict->file_loc_init_value
3780
0
    = 0;
3781
0
        som_section_data (subsection)->subspace_dict->
3782
0
    initialization_length = 0;
3783
0
      }
3784
0
  }
3785
      /* Goto the next section.  */
3786
0
      section = section->next;
3787
0
    }
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
0
  if (abfd->flags & (EXEC_P | DYNAMIC))
3794
0
    current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
3795
3796
0
  obj_som_file_hdr (abfd)->unloadable_sp_location = current_offset;
3797
0
  section = abfd->sections;
3798
0
  for (i = 0; i < num_spaces; i++)
3799
0
    {
3800
0
      asection *subsection;
3801
3802
      /* Find a space.  */
3803
0
      while (!som_is_space (section))
3804
0
  section = section->next;
3805
3806
0
      if (abfd->flags & (EXEC_P | DYNAMIC))
3807
0
  current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
3808
3809
      /* Now look for all its subspaces.  */
3810
0
      for (subsection = abfd->sections;
3811
0
     subsection != NULL;
3812
0
     subsection = subsection->next)
3813
0
  {
3814
3815
0
    if (!som_is_subspace (subsection)
3816
0
        || !som_is_container (section, subsection)
3817
0
        || (subsection->flags & SEC_ALLOC) != 0)
3818
0
      continue;
3819
3820
0
    subsection->target_index = total_subspaces++;
3821
    /* This is real data to be loaded from the file.  */
3822
0
    if ((subsection->flags & SEC_LOAD) == 0)
3823
0
      {
3824
0
        som_section_data (subsection)->subspace_dict->file_loc_init_value
3825
0
    = current_offset;
3826
0
        subsection->filepos = current_offset;
3827
0
        current_offset += subsection->size;
3828
0
      }
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
0
  }
3838
      /* Goto the next section.  */
3839
0
      section = section->next;
3840
0
    }
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
0
  if (abfd->flags & (EXEC_P | DYNAMIC))
3846
0
    current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
3847
0
  if (bfd_seek (abfd, current_offset - 1, SEEK_SET) != 0)
3848
0
    return false;
3849
0
  if (bfd_write ("", 1, abfd) != 1)
3850
0
    return false;
3851
3852
0
  obj_som_file_hdr (abfd)->unloadable_sp_size
3853
0
    = current_offset - obj_som_file_hdr (abfd)->unloadable_sp_location;
3854
3855
  /* Loader fixups are not supported in any way shape or form.  */
3856
0
  obj_som_file_hdr (abfd)->loader_fixup_location = 0;
3857
0
  obj_som_file_hdr (abfd)->loader_fixup_total = 0;
3858
3859
  /* Done.  Store the total size of the SOM so far.  */
3860
0
  obj_som_file_hdr (abfd)->som_length = current_offset;
3861
3862
0
  return true;
3863
0
}
3864
3865
/* Finally, scribble out the various headers to the disk.  */
3866
3867
static bool
3868
som_finish_writing (bfd *abfd)
3869
0
{
3870
0
  int num_spaces = som_count_spaces (abfd);
3871
0
  asymbol **syms = bfd_get_outsymbols (abfd);
3872
0
  int i, num_syms;
3873
0
  int subspace_index = 0;
3874
0
  file_ptr location;
3875
0
  asection *section;
3876
0
  unsigned long current_offset;
3877
0
  unsigned int strings_size, total_reloc_size;
3878
0
  size_t amt;
3879
0
  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
0
  if (obj_som_exec_data (abfd)
3884
0
      && obj_som_exec_data (abfd)->version_id)
3885
0
    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
0
  current_offset = obj_som_file_hdr (abfd)->som_length;
3903
3904
  /* Make sure we're on a word boundary.  */
3905
0
  if (current_offset % 4)
3906
0
    current_offset += (4 - (current_offset % 4));
3907
3908
0
  num_syms = bfd_get_symcount (abfd);
3909
0
  obj_som_file_hdr (abfd)->symbol_location = current_offset;
3910
0
  obj_som_file_hdr (abfd)->symbol_total = num_syms;
3911
0
  current_offset +=
3912
0
    num_syms * sizeof (struct som_external_symbol_dictionary_record);
3913
3914
  /* Next are the symbol strings.
3915
     Align them to a word boundary.  */
3916
0
  if (current_offset % 4)
3917
0
    current_offset += (4 - (current_offset % 4));
3918
0
  obj_som_file_hdr (abfd)->symbol_strings_location = current_offset;
3919
3920
  /* Scribble out the symbol strings.  */
3921
0
  if (! som_write_symbol_strings (abfd, current_offset, syms,
3922
0
          num_syms, &strings_size,
3923
0
          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
0
  obj_som_file_hdr (abfd)->symbol_strings_size = strings_size;
3929
0
  current_offset += strings_size;
3930
3931
  /* Do prep work before handling fixups.  */
3932
0
  if (!som_prep_for_fixups (abfd,
3933
0
          bfd_get_outsymbols (abfd),
3934
0
          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
0
  if (current_offset % 4)
3940
0
    current_offset += (4 - (current_offset % 4));
3941
0
  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
0
  if (! som_write_fixups (abfd, current_offset, &total_reloc_size))
3946
0
    return false;
3947
3948
  /* Record the total size of the fixup stream in the file header.  */
3949
0
  obj_som_file_hdr (abfd)->fixup_request_total = total_reloc_size;
3950
3951
  /* Done.  Store the total size of the SOM.  */
3952
0
  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
0
  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
0
  location = obj_som_file_hdr (abfd)->subspace_location;
3964
0
  if (bfd_seek (abfd, location, SEEK_SET) != 0)
3965
0
    return false;
3966
3967
0
  section = abfd->sections;
3968
  /* Now for each loadable space write out records for its subspaces.  */
3969
0
  for (i = 0; i < num_spaces; i++)
3970
0
    {
3971
0
      asection *subsection;
3972
3973
      /* Find a space.  */
3974
0
      while (!som_is_space (section))
3975
0
  section = section->next;
3976
3977
      /* Now look for all its subspaces.  */
3978
0
      for (subsection = abfd->sections;
3979
0
     subsection != NULL;
3980
0
     subsection = subsection->next)
3981
0
  {
3982
0
    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
0
    if (!som_is_subspace (subsection)
3988
0
        || !som_is_container (section, subsection)
3989
0
        || (subsection->flags & SEC_ALLOC) == 0)
3990
0
      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
0
    if (som_section_data (section)->space_dict->subspace_quantity == 0)
3997
0
      {
3998
0
        som_section_data (section)->space_dict->is_loadable = 1;
3999
0
        som_section_data (section)->space_dict->subspace_index
4000
0
    = subspace_index;
4001
0
      }
4002
4003
    /* Increment the number of subspaces seen and the number of
4004
       subspaces contained within the current space.  */
4005
0
    subspace_index++;
4006
0
    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
0
    som_section_data (subsection)->subspace_dict->space_index = i;
4011
4012
    /* Dump the current subspace header.  */
4013
0
    som_swap_subspace_dictionary_record_out
4014
0
      (som_section_data (subsection)->subspace_dict, &ext_subspace_dict);
4015
0
    amt = sizeof (struct som_subspace_dictionary_record);
4016
0
    if (bfd_write (&ext_subspace_dict, amt, abfd) != amt)
4017
0
      return false;
4018
0
  }
4019
      /* Goto the next section.  */
4020
0
      section = section->next;
4021
0
    }
4022
4023
  /* Now repeat the process for unloadable subspaces.  */
4024
0
  section = abfd->sections;
4025
  /* Now for each space write out records for its subspaces.  */
4026
0
  for (i = 0; i < num_spaces; i++)
4027
0
    {
4028
0
      asection *subsection;
4029
4030
      /* Find a space.  */
4031
0
      while (!som_is_space (section))
4032
0
  section = section->next;
4033
4034
      /* Now look for all its subspaces.  */
4035
0
      for (subsection = abfd->sections;
4036
0
     subsection != NULL;
4037
0
     subsection = subsection->next)
4038
0
  {
4039
0
    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
0
    if (!som_is_subspace (subsection)
4046
0
        || !som_is_container (section, subsection)
4047
0
        || (subsection->flags & SEC_ALLOC) != 0)
4048
0
      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
0
    if (som_section_data (section)->space_dict->subspace_quantity == 0)
4055
0
      {
4056
0
        som_section_data (section)->space_dict->is_loadable = 0;
4057
0
        som_section_data (section)->space_dict->subspace_index
4058
0
    = subspace_index;
4059
0
      }
4060
4061
    /* Increment the number of subspaces seen and the number of
4062
       subspaces contained within the current space.  */
4063
0
    som_section_data (section)->space_dict->subspace_quantity++;
4064
0
    subspace_index++;
4065
4066
    /* Mark the index of the current space within the subspace's
4067
       dictionary record.  */
4068
0
    som_section_data (subsection)->subspace_dict->space_index = i;
4069
4070
    /* Dump this subspace header.  */
4071
0
    som_swap_subspace_dictionary_record_out
4072
0
      (som_section_data (subsection)->subspace_dict, &ext_subspace_dict);
4073
0
    amt = sizeof (struct som_subspace_dictionary_record);
4074
0
    if (bfd_write (&ext_subspace_dict, amt, abfd) != amt)
4075
0
      return false;
4076
0
  }
4077
      /* Goto the next section.  */
4078
0
      section = section->next;
4079
0
    }
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
0
  location = obj_som_file_hdr (abfd)->space_location;
4087
0
  if (bfd_seek (abfd, location, SEEK_SET) != 0)
4088
0
    return false;
4089
4090
0
  section = abfd->sections;
4091
0
  for (i = 0; i < num_spaces; i++)
4092
0
    {
4093
0
      struct som_external_space_dictionary_record ext_space_dict;
4094
4095
      /* Find a space.  */
4096
0
      while (!som_is_space (section))
4097
0
  section = section->next;
4098
4099
      /* Dump its header.  */
4100
0
      som_swap_space_dictionary_out (som_section_data (section)->space_dict,
4101
0
             &ext_space_dict);
4102
0
      amt = sizeof (struct som_external_space_dictionary_record);
4103
0
      if (bfd_write (&ext_space_dict, amt, abfd) != amt)
4104
0
  return false;
4105
4106
      /* Goto the next section.  */
4107
0
      section = section->next;
4108
0
    }
4109
4110
  /* Write the compilation unit record if there is one.  */
4111
0
  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
0
  if ((abfd->flags & (EXEC_P | DYNAMIC)) && obj_som_exec_data (abfd))
4130
0
    obj_som_file_hdr (abfd)->system_id = obj_som_exec_data (abfd)->system_id;
4131
0
  else if (bfd_get_mach (abfd) == pa20)
4132
0
    obj_som_file_hdr (abfd)->system_id = CPU_PA_RISC2_0;
4133
0
  else if (bfd_get_mach (abfd) == pa11)
4134
0
    obj_som_file_hdr (abfd)->system_id = CPU_PA_RISC1_1;
4135
0
  else
4136
0
    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
0
  som_swap_header_out (obj_som_file_hdr (abfd), &ext_header);
4141
0
  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
0
  if (bfd_seek (abfd, 0, SEEK_SET) != 0)
4146
0
    return false;
4147
0
  amt = sizeof (struct som_external_header);
4148
0
  if (bfd_write (&ext_header, amt, abfd) != amt)
4149
0
    return false;
4150
4151
  /* Now write the exec header.  */
4152
0
  if (abfd->flags & (EXEC_P | DYNAMIC))
4153
0
    {
4154
0
      long tmp, som_length;
4155
0
      struct som_exec_auxhdr *exec_header;
4156
0
      struct som_external_exec_auxhdr ext_exec_header;
4157
4158
0
      exec_header = obj_som_exec_hdr (abfd);
4159
0
      exec_header->exec_entry = bfd_get_start_address (abfd);
4160
0
      if (obj_som_exec_data (abfd))
4161
0
  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
0
      tmp = exec_header->exec_dsize;
4167
0
      tmp = SOM_ALIGN (tmp, PA_PAGESIZE);
4168
0
      exec_header->exec_bsize -= (tmp - exec_header->exec_dsize);
4169
0
      if (exec_header->exec_bsize < 0)
4170
0
  exec_header->exec_bsize = 0;
4171
0
      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
0
      som_length = obj_som_file_hdr (abfd)->som_length;
4176
0
      if (exec_header->exec_tfile + exec_header->exec_tsize > som_length
4177
0
    || 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
0
      som_swap_exec_auxhdr_out (exec_header, &ext_exec_header);
4184
4185
0
      if (bfd_seek (abfd, obj_som_file_hdr (abfd)->aux_header_location,
4186
0
        SEEK_SET) != 0)
4187
0
  return false;
4188
4189
0
      amt = sizeof (ext_exec_header);
4190
0
      if (bfd_write (&ext_exec_header, amt, abfd) != amt)
4191
0
  return false;
4192
0
    }
4193
0
  return true;
4194
0
}
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
0
{
4201
0
  size_t count, i;
4202
0
  uint32_t checksum;
4203
0
  uint32_t *buffer = (uint32_t *) hdr;
4204
4205
0
  checksum = 0;
4206
0
  count = sizeof (*hdr) / sizeof (*buffer);
4207
0
  for (i = 0; i < count; i++)
4208
0
    checksum ^= *(buffer + i);
4209
4210
0
  return checksum;
4211
0
}
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
0
{
4218
  /* Initialize.  */
4219
0
  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
0
  if (sym->flags & BSF_SECTION_SYM)
4229
0
    info->symbol_type = ST_DATA;
4230
0
  else
4231
0
    {
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
0
      if (bfd_is_com_section (sym->section))
4235
0
  {
4236
0
    info->symbol_type = ST_STORAGE;
4237
0
    info->symbol_scope = SS_UNSAT;
4238
0
  }
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
0
      else if ((som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN
4247
0
    || som_symbol_data (sym)->som_type == SYMBOL_TYPE_CODE)
4248
0
         && bfd_is_und_section (sym->section)
4249
0
         && sym->flags & BSF_FUNCTION)
4250
0
  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
0
      else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_ENTRY
4256
0
         || (som_symbol_data (sym)->som_type == SYMBOL_TYPE_CODE
4257
0
       && (sym->flags & BSF_FUNCTION))
4258
0
         || (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN
4259
0
       && (sym->flags & BSF_FUNCTION)))
4260
0
  {
4261
0
    info->symbol_type = ST_ENTRY;
4262
0
    info->arg_reloc = som_symbol_data (sym)->tc_data.ap.hppa_arg_reloc;
4263
0
    info->priv_level= som_symbol_data (sym)->tc_data.ap.hppa_priv_level;
4264
0
  }
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
0
      else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN)
4269
0
  {
4270
0
    if (bfd_is_abs_section (sym->section))
4271
0
      info->symbol_type = ST_ABSOLUTE;
4272
0
    else if (sym->section->flags & SEC_CODE)
4273
0
      info->symbol_type = ST_CODE;
4274
0
    else
4275
0
      info->symbol_type = ST_DATA;
4276
0
  }
4277
4278
      /* From now on it's a very simple mapping.  */
4279
0
      else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_ABSOLUTE)
4280
0
  info->symbol_type = ST_ABSOLUTE;
4281
0
      else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_CODE)
4282
0
  info->symbol_type = ST_CODE;
4283
0
      else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_DATA)
4284
0
  info->symbol_type = ST_DATA;
4285
0
      else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_MILLICODE)
4286
0
  info->symbol_type = ST_MILLICODE;
4287
0
      else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_PLABEL)
4288
0
  info->symbol_type = ST_PLABEL;
4289
0
      else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_PRI_PROG)
4290
0
  info->symbol_type = ST_PRI_PROG;
4291
0
      else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_SEC_PROG)
4292
0
  info->symbol_type = ST_SEC_PROG;
4293
0
    }
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
0
  if (bfd_is_com_section (sym->section))
4299
0
    ;
4300
0
  else if (bfd_is_und_section (sym->section))
4301
0
    info->symbol_scope = SS_UNSAT;
4302
0
  else if (sym->flags & (BSF_EXPORT | BSF_WEAK))
4303
0
    info->symbol_scope = SS_UNIVERSAL;
4304
  /* Anything else which is not in the common section has scope
4305
     SS_LOCAL.  */
4306
0
  else
4307
0
    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
0
  if (bfd_is_com_section (sym->section)
4314
0
      || bfd_is_und_section (sym->section)
4315
0
      || bfd_is_abs_section (sym->section))
4316
0
    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
0
  info->symbol_value = sym->value + sym->section->vma;
4324
4325
  /* The secondary_def field is for "weak" symbols.  */
4326
0
  if (sym->flags & BSF_WEAK)
4327
0
    info->secondary_def = true;
4328
0
  else
4329
0
    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
0
  if (som_section_data (sym->section)
4355
0
      && som_section_data (sym->section)->subspace_dict
4356
0
      && info->symbol_scope == SS_UNIVERSAL
4357
0
      && (info->symbol_type == ST_ENTRY
4358
0
    || info->symbol_type == ST_CODE
4359
0
    || info->symbol_type == ST_DATA))
4360
0
    {
4361
0
      info->is_comdat
4362
0
  = som_section_data (sym->section)->subspace_dict->is_comdat;
4363
0
      info->is_common
4364
0
  = som_section_data (sym->section)->subspace_dict->is_common;
4365
0
      info->dup_common
4366
0
  = som_section_data (sym->section)->subspace_dict->dup_common;
4367
0
    }
4368
0
}
4369
4370
/* Build and write, in one big chunk, the entire symbol table for
4371
   this BFD.  */
4372
4373
static bool
4374
som_build_and_write_symbol_table (bfd *abfd)
4375
0
{
4376
0
  unsigned int num_syms = bfd_get_symcount (abfd);
4377
0
  file_ptr symtab_location = obj_som_file_hdr (abfd)->symbol_location;
4378
0
  asymbol **bfd_syms = obj_som_sorted_syms (abfd);
4379
0
  struct som_external_symbol_dictionary_record *som_symtab = NULL;
4380
0
  unsigned int i;
4381
0
  bfd_size_type symtab_size;
4382
0
  size_t amt;
4383
4384
  /* Compute total symbol table size and allocate a chunk of memory
4385
     to hold the symbol table as we build it.  */
4386
0
  if (_bfd_mul_overflow (num_syms,
4387
0
       sizeof (struct som_external_symbol_dictionary_record),
4388
0
       &amt))
4389
0
    {
4390
0
      bfd_set_error (bfd_error_no_memory);
4391
0
      return false;
4392
0
    }
4393
0
  som_symtab = bfd_zmalloc (amt);
4394
0
  if (som_symtab == NULL && num_syms != 0)
4395
0
    goto error_return;
4396
4397
  /* Walk over each symbol.  */
4398
0
  for (i = 0; i < num_syms; i++)
4399
0
    {
4400
0
      struct som_misc_symbol_info info;
4401
0
      unsigned int flags;
4402
4403
      /* This is really an index into the symbol strings table.
4404
   By the time we get here, the index has already been
4405
   computed and stored into the name field in the BFD symbol.  */
4406
0
      bfd_putb32 (som_symbol_data (bfd_syms[i])->stringtab_offset,
4407
0
      som_symtab[i].name);
4408
4409
      /* Derive SOM information from the BFD symbol.  */
4410
0
      som_bfd_derive_misc_symbol_info (abfd, bfd_syms[i], &info);
4411
4412
      /* Now use it.  */
4413
0
      flags = (info.symbol_type << SOM_SYMBOL_TYPE_SH)
4414
0
  | (info.symbol_scope << SOM_SYMBOL_SCOPE_SH)
4415
0
  | (info.arg_reloc << SOM_SYMBOL_ARG_RELOC_SH)
4416
0
  | (3 << SOM_SYMBOL_XLEAST_SH)
4417
0
  | (info.secondary_def ? SOM_SYMBOL_SECONDARY_DEF : 0)
4418
0
  | (info.is_common ? SOM_SYMBOL_IS_COMMON : 0)
4419
0
  | (info.dup_common ? SOM_SYMBOL_DUP_COMMON : 0);
4420
0
      bfd_putb32 (flags, som_symtab[i].flags);
4421
4422
0
      flags = (info.symbol_info << SOM_SYMBOL_SYMBOL_INFO_SH)
4423
0
  | (info.is_comdat ? SOM_SYMBOL_IS_COMDAT : 0);
4424
0
      bfd_putb32 (flags, som_symtab[i].info);
4425
0
      bfd_putb32 (info.symbol_value | info.priv_level,
4426
0
      som_symtab[i].symbol_value);
4427
0
    }
4428
4429
  /* Everything is ready, seek to the right location and
4430
     scribble out the symbol table.  */
4431
0
  if (bfd_seek (abfd, symtab_location, SEEK_SET) != 0)
4432
0
    goto error_return;
4433
4434
0
  symtab_size = num_syms;
4435
0
  symtab_size *= sizeof (struct som_external_symbol_dictionary_record);
4436
0
  if (bfd_write (som_symtab, symtab_size, abfd) != symtab_size)
4437
0
    goto error_return;
4438
4439
0
  free (som_symtab);
4440
0
  return true;
4441
4442
0
 error_return:
4443
0
  free (som_symtab);
4444
0
  return false;
4445
0
}
4446
4447
/* Write an object in SOM format.  */
4448
4449
static bool
4450
som_write_object_contents (bfd *abfd)
4451
0
{
4452
0
  if (! abfd->output_has_begun)
4453
0
    {
4454
      /* Set up fixed parts of the file, space, and subspace headers.
4455
   Notify the world that output has begun.  */
4456
0
      som_prep_headers (abfd);
4457
0
      abfd->output_has_begun = true;
4458
      /* Start writing the object file.  This include all the string
4459
   tables, fixup streams, and other portions of the object file.  */
4460
0
      som_begin_writing (abfd);
4461
0
    }
4462
4463
0
  return som_finish_writing (abfd);
4464
0
}
4465

4466
/* Read and save the string table associated with the given BFD.  */
4467
4468
static bool
4469
som_slurp_string_table (bfd *abfd)
4470
591
{
4471
591
  char *stringtab;
4472
591
  bfd_size_type amt;
4473
4474
  /* Use the saved version if its available.  */
4475
591
  if (obj_som_stringtab (abfd) != NULL)
4476
0
    return true;
4477
4478
  /* I don't think this can currently happen, and I'm not sure it should
4479
     really be an error, but it's better than getting unpredictable results
4480
     from the host's malloc when passed a size of zero.  */
4481
591
  if (obj_som_stringtab_size (abfd) == 0)
4482
27
    {
4483
27
      bfd_set_error (bfd_error_no_symbols);
4484
27
      return false;
4485
27
    }
4486
4487
  /* Allocate and read in the string table.  */
4488
564
  if (bfd_seek (abfd, obj_som_str_filepos (abfd), SEEK_SET) != 0)
4489
0
    return false;
4490
564
  amt = obj_som_stringtab_size (abfd);
4491
564
  stringtab = (char *) _bfd_malloc_and_read (abfd, amt + 1, amt);
4492
564
  if (stringtab == NULL)
4493
122
    return false;
4494
  /* Make sure that the strings are zero-terminated.  */
4495
442
  stringtab[amt] = 0;
4496
4497
  /* Save our results and return success.  */
4498
442
  obj_som_stringtab (abfd) = stringtab;
4499
442
  return true;
4500
564
}
4501
4502
/* Return the amount of data (in bytes) required to hold the symbol
4503
   table for this object.  */
4504
4505
static long
4506
som_get_symtab_upper_bound (bfd *abfd)
4507
837
{
4508
837
  if (!som_slurp_symbol_table (abfd))
4509
273
    return -1;
4510
4511
564
  return (bfd_get_symcount (abfd) + 1) * sizeof (asymbol *);
4512
837
}
4513
4514
/* Convert from a SOM subspace index to a BFD section.  */
4515
4516
asection *
4517
bfd_section_from_som_symbol
4518
  (bfd *abfd, struct som_external_symbol_dictionary_record *symbol)
4519
401
{
4520
401
  asection *section;
4521
401
  unsigned int flags = bfd_getb32 (symbol->flags);
4522
401
  unsigned int symbol_type = (flags >> SOM_SYMBOL_TYPE_SH) & SOM_SYMBOL_TYPE_MASK;
4523
4524
  /* The meaning of the symbol_info field changes for functions
4525
     within executables.  So only use the quick symbol_info mapping for
4526
     incomplete objects and non-function symbols in executables.  */
4527
401
  if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0
4528
401
      || (symbol_type != ST_ENTRY
4529
264
    && symbol_type != ST_PRI_PROG
4530
264
    && symbol_type != ST_SEC_PROG
4531
264
    && symbol_type != ST_MILLICODE))
4532
218
    {
4533
218
      int idx = (bfd_getb32 (symbol->info) >> SOM_SYMBOL_SYMBOL_INFO_SH)
4534
218
  & SOM_SYMBOL_SYMBOL_INFO_MASK;
4535
4536
1.12k
      for (section = abfd->sections; section != NULL; section = section->next)
4537
923
  if (section->target_index == idx && som_is_subspace (section))
4538
14
    return section;
4539
218
    }
4540
183
  else
4541
183
    {
4542
183
      unsigned int value = bfd_getb32 (symbol->symbol_value);
4543
4544
      /* For executables we will have to use the symbol's address and
4545
   find out what section would contain that address.   Yuk.  */
4546
458
      for (section = abfd->sections; section; section = section->next)
4547
343
  if (value >= section->vma
4548
343
      && value <= section->vma + section->size
4549
343
      && som_is_subspace (section))
4550
68
    return section;
4551
183
    }
4552
4553
  /* Could be a symbol from an external library (such as an OMOS
4554
     shared library).  Don't abort.  */
4555
319
  return bfd_abs_section_ptr;
4556
401
}
4557
4558
/* Read and save the symbol table associated with the given BFD.  */
4559
4560
static unsigned int
4561
som_slurp_symbol_table (bfd *abfd)
4562
1.40k
{
4563
1.40k
  unsigned int symbol_count = bfd_get_symcount (abfd);
4564
1.40k
  size_t symsize = sizeof (struct som_external_symbol_dictionary_record);
4565
1.40k
  char *stringtab;
4566
1.40k
  struct som_external_symbol_dictionary_record *buf = NULL, *bufp, *endbufp;
4567
1.40k
  som_symbol_type *sym, *symbase = NULL;
4568
1.40k
  size_t amt;
4569
4570
  /* Return saved value if it exists.  */
4571
1.40k
  if (obj_som_symtab (abfd) != NULL)
4572
810
    goto successful_return;
4573
4574
  /* Special case.  This is *not* an error.  */
4575
591
  if (symbol_count == 0)
4576
0
    goto successful_return;
4577
4578
591
  if (!som_slurp_string_table (abfd))
4579
149
    goto error_return;
4580
4581
442
  stringtab = obj_som_stringtab (abfd);
4582
4583
  /* Read in the external SOM representation.  */
4584
442
  if (_bfd_mul_overflow (symbol_count, symsize, &amt))
4585
0
    {
4586
0
      bfd_set_error (bfd_error_file_too_big);
4587
0
      goto error_return;
4588
0
    }
4589
442
  if (bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET) != 0)
4590
0
    goto error_return;
4591
442
  buf = (struct som_external_symbol_dictionary_record *)
4592
442
    _bfd_malloc_and_read (abfd, amt, amt);
4593
442
  if (buf == NULL)
4594
7
    goto error_return;
4595
4596
435
  if (_bfd_mul_overflow (symbol_count, sizeof (som_symbol_type), &amt))
4597
0
    {
4598
0
      bfd_set_error (bfd_error_file_too_big);
4599
0
      goto error_return;
4600
0
    }
4601
435
  symbase = bfd_zmalloc (amt);
4602
435
  if (symbase == NULL)
4603
0
    goto error_return;
4604
4605
  /* Iterate over all the symbols and internalize them.  */
4606
435
  endbufp = buf + symbol_count;
4607
10.5k
  for (bufp = buf, sym = symbase; bufp < endbufp; ++bufp)
4608
10.2k
    {
4609
10.2k
      unsigned int flags = bfd_getb32 (bufp->flags);
4610
10.2k
      unsigned int symbol_type =
4611
10.2k
  (flags >> SOM_SYMBOL_TYPE_SH) & SOM_SYMBOL_TYPE_MASK;
4612
10.2k
      unsigned int symbol_scope =
4613
10.2k
  (flags >> SOM_SYMBOL_SCOPE_SH) & SOM_SYMBOL_SCOPE_MASK;
4614
10.2k
      bfd_vma offset;
4615
4616
      /* I don't think we care about these.  */
4617
10.2k
      if (symbol_type == ST_SYM_EXT || symbol_type == ST_ARG_EXT)
4618
1.45k
  continue;
4619
4620
      /* Set some private data we care about.  */
4621
8.80k
      if (symbol_type == ST_NULL)
4622
7.91k
  som_symbol_data (sym)->som_type = SYMBOL_TYPE_UNKNOWN;
4623
882
      else if (symbol_type == ST_ABSOLUTE)
4624
46
  som_symbol_data (sym)->som_type = SYMBOL_TYPE_ABSOLUTE;
4625
836
      else if (symbol_type == ST_DATA)
4626
26
  som_symbol_data (sym)->som_type = SYMBOL_TYPE_DATA;
4627
810
      else if (symbol_type == ST_CODE)
4628
26
  som_symbol_data (sym)->som_type = SYMBOL_TYPE_CODE;
4629
784
      else if (symbol_type == ST_PRI_PROG)
4630
52
  som_symbol_data (sym)->som_type = SYMBOL_TYPE_PRI_PROG;
4631
732
      else if (symbol_type == ST_SEC_PROG)
4632
44
  som_symbol_data (sym)->som_type = SYMBOL_TYPE_SEC_PROG;
4633
688
      else if (symbol_type == ST_ENTRY)
4634
121
  som_symbol_data (sym)->som_type = SYMBOL_TYPE_ENTRY;
4635
567
      else if (symbol_type == ST_MILLICODE)
4636
43
  som_symbol_data (sym)->som_type = SYMBOL_TYPE_MILLICODE;
4637
524
      else if (symbol_type == ST_PLABEL)
4638
24
  som_symbol_data (sym)->som_type = SYMBOL_TYPE_PLABEL;
4639
500
      else
4640
500
  som_symbol_data (sym)->som_type = SYMBOL_TYPE_UNKNOWN;
4641
8.80k
      som_symbol_data (sym)->tc_data.ap.hppa_arg_reloc =
4642
8.80k
  (flags >> SOM_SYMBOL_ARG_RELOC_SH) & SOM_SYMBOL_ARG_RELOC_MASK;
4643
4644
      /* Some reasonable defaults.  */
4645
8.80k
      sym->symbol.the_bfd = abfd;
4646
8.80k
      offset = bfd_getb32 (bufp->name);
4647
8.80k
      if (offset < obj_som_stringtab_size (abfd))
4648
8.68k
  sym->symbol.name = offset + stringtab;
4649
117
      else
4650
117
  {
4651
117
    bfd_set_error (bfd_error_bad_value);
4652
117
    goto error_return;
4653
117
  }
4654
8.68k
      sym->symbol.value = bfd_getb32 (bufp->symbol_value);
4655
8.68k
      sym->symbol.section = NULL;
4656
8.68k
      sym->symbol.flags = 0;
4657
4658
8.68k
      switch (symbol_type)
4659
8.68k
  {
4660
119
  case ST_ENTRY:
4661
161
  case ST_MILLICODE:
4662
161
    sym->symbol.flags |= BSF_FUNCTION;
4663
161
    som_symbol_data (sym)->tc_data.ap.hppa_priv_level =
4664
161
      sym->symbol.value & 0x3;
4665
161
    sym->symbol.value &= ~0x3;
4666
161
    break;
4667
4668
12
  case ST_STUB:
4669
35
  case ST_CODE:
4670
85
  case ST_PRI_PROG:
4671
124
  case ST_SEC_PROG:
4672
124
    som_symbol_data (sym)->tc_data.ap.hppa_priv_level =
4673
124
      sym->symbol.value & 0x3;
4674
124
    sym->symbol.value &= ~0x3;
4675
    /* If the symbol's scope is SS_UNSAT, then these are
4676
       undefined function symbols.  */
4677
124
    if (symbol_scope == SS_UNSAT)
4678
37
      sym->symbol.flags |= BSF_FUNCTION;
4679
4680
8.52k
  default:
4681
8.52k
    break;
4682
8.68k
  }
4683
4684
      /* Handle scoping and section information.  */
4685
8.68k
      switch (symbol_scope)
4686
8.68k
  {
4687
  /* symbol_info field is undefined for SS_EXTERNAL and SS_UNSAT symbols,
4688
     so the section associated with this symbol can't be known.  */
4689
50
  case SS_EXTERNAL:
4690
50
    if (symbol_type != ST_STORAGE)
4691
36
      sym->symbol.section = bfd_und_section_ptr;
4692
14
    else
4693
14
      sym->symbol.section = bfd_com_section_ptr;
4694
50
    sym->symbol.flags |= (BSF_EXPORT | BSF_GLOBAL);
4695
50
    break;
4696
4697
7.93k
  case SS_UNSAT:
4698
7.93k
    if (symbol_type != ST_STORAGE)
4699
7.89k
      sym->symbol.section = bfd_und_section_ptr;
4700
32
    else
4701
32
      sym->symbol.section = bfd_com_section_ptr;
4702
7.93k
    break;
4703
4704
139
  case SS_UNIVERSAL:
4705
139
    sym->symbol.flags |= (BSF_EXPORT | BSF_GLOBAL);
4706
139
    sym->symbol.section = bfd_section_from_som_symbol (abfd, bufp);
4707
139
    sym->symbol.value -= sym->symbol.section->vma;
4708
139
    break;
4709
4710
262
  case SS_LOCAL:
4711
262
    sym->symbol.flags |= BSF_LOCAL;
4712
262
    sym->symbol.section = bfd_section_from_som_symbol (abfd, bufp);
4713
262
    sym->symbol.value -= sym->symbol.section->vma;
4714
262
    break;
4715
4716
303
  default:
4717
303
    sym->symbol.section = bfd_und_section_ptr;
4718
303
    break;
4719
8.68k
  }
4720
4721
      /* Check for a weak symbol.  */
4722
8.68k
      if (flags & SOM_SYMBOL_SECONDARY_DEF)
4723
312
  sym->symbol.flags |= BSF_WEAK;
4724
      /* Mark section symbols and symbols used by the debugger.
4725
   Note $START$ is a magic code symbol, NOT a section symbol.  */
4726
8.68k
      if (sym->symbol.name[0] == '$'
4727
8.68k
    && sym->symbol.name[strlen (sym->symbol.name) - 1] == '$'
4728
8.68k
    && !strcmp (sym->symbol.name, sym->symbol.section->name))
4729
0
  sym->symbol.flags |= BSF_SECTION_SYM;
4730
8.68k
      else if (startswith (sym->symbol.name, "L$0\002"))
4731
19
  {
4732
19
    sym->symbol.flags |= BSF_SECTION_SYM;
4733
19
    sym->symbol.name = sym->symbol.section->name;
4734
19
  }
4735
8.66k
      else if (startswith (sym->symbol.name, "L$0\001"))
4736
29
  sym->symbol.flags |= BSF_DEBUGGING;
4737
      /* Note increment at bottom of loop, since we skip some symbols
4738
   we can not include it as part of the for statement.  */
4739
8.68k
      sym++;
4740
8.68k
    }
4741
4742
  /* We modify the symbol count to record the number of BFD symbols we
4743
     created.  */
4744
318
  abfd->symcount = sym - symbase;
4745
4746
  /* Save our results and return success.  */
4747
318
  obj_som_symtab (abfd) = symbase;
4748
1.12k
 successful_return:
4749
1.12k
  free (buf);
4750
1.12k
  return true;
4751
4752
273
 error_return:
4753
273
  free (symbase);
4754
273
  free (buf);
4755
273
  return false;
4756
318
}
4757
4758
/* Canonicalize a SOM symbol table.  Return the number of entries
4759
   in the symbol table.  */
4760
4761
static long
4762
som_canonicalize_symtab (bfd *abfd, asymbol **location)
4763
564
{
4764
564
  int i;
4765
564
  som_symbol_type *symbase;
4766
4767
564
  if (!som_slurp_symbol_table (abfd))
4768
0
    return -1;
4769
4770
564
  i = bfd_get_symcount (abfd);
4771
564
  symbase = obj_som_symtab (abfd);
4772
4773
9.57k
  for (; i > 0; i--, location++, symbase++)
4774
9.00k
    *location = &symbase->symbol;
4775
4776
  /* Final null pointer.  */
4777
564
  *location = 0;
4778
564
  return (bfd_get_symcount (abfd));
4779
564
}
4780
4781
/* Make a SOM symbol.  There is nothing special to do here.  */
4782
4783
static asymbol *
4784
som_make_empty_symbol (bfd *abfd)
4785
81.1k
{
4786
81.1k
  size_t amt = sizeof (som_symbol_type);
4787
81.1k
  som_symbol_type *new_symbol_type = bfd_zalloc (abfd, amt);
4788
4789
81.1k
  if (new_symbol_type == NULL)
4790
0
    return NULL;
4791
81.1k
  new_symbol_type->symbol.the_bfd = abfd;
4792
4793
81.1k
  return &new_symbol_type->symbol;
4794
81.1k
}
4795
4796
/* Print symbol information.  */
4797
4798
static void
4799
som_print_symbol (bfd *abfd,
4800
      void *afile,
4801
      asymbol *symbol,
4802
      bfd_print_symbol_type how)
4803
0
{
4804
0
  FILE *file = (FILE *) afile;
4805
4806
0
  switch (how)
4807
0
    {
4808
0
    case bfd_print_symbol_name:
4809
0
      fprintf (file, "%s", symbol->name);
4810
0
      break;
4811
0
    case bfd_print_symbol_more:
4812
0
      fprintf (file, "som %08" PRIx64 " %x",
4813
0
         (uint64_t) symbol->value, symbol->flags);
4814
0
      break;
4815
0
    case bfd_print_symbol_all:
4816
0
      {
4817
0
  const char *section_name;
4818
4819
0
  section_name = symbol->section ? symbol->section->name : "(*none*)";
4820
0
  bfd_print_symbol_vandf (abfd, (void *) file, symbol);
4821
0
  fprintf (file, " %s\t%s", section_name, symbol->name);
4822
0
  break;
4823
0
      }
4824
0
    }
4825
0
}
4826
4827
static bool
4828
som_bfd_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED,
4829
           const char *name)
4830
0
{
4831
0
  return name[0] == 'L' && name[1] == '$';
4832
0
}
4833
4834
/* Count or process variable-length SOM fixup records.
4835
4836
   To avoid code duplication we use this code both to compute the number
4837
   of relocations requested by a stream, and to internalize the stream.
4838
4839
   When computing the number of relocations requested by a stream the
4840
   variables rptr, section, and symbols have no meaning.
4841
4842
   Return the number of relocations requested by the fixup stream.  When
4843
   not just counting
4844
4845
   This needs at least two or three more passes to get it cleaned up.  */
4846
4847
static unsigned int
4848
som_set_reloc_info (unsigned char *fixup,
4849
        unsigned int end,
4850
        arelent *internal_relocs,
4851
        asection *section,
4852
        asymbol **symbols,
4853
        unsigned int symcount,
4854
        bool just_count)
4855
542
{
4856
542
  unsigned int deallocate_contents = 0;
4857
542
  unsigned char *end_fixups = &fixup[end];
4858
542
  int variables[26], stack[20], count, prev_fixup, *sp, saved_unwind_bits;
4859
542
  arelent *rptr = internal_relocs;
4860
542
  unsigned int offset = 0;
4861
4862
357k
#define var(c)    variables[(c) - 'A']
4863
296k
#define push(v)   (*sp++ = (v))
4864
296k
#define pop()   (*--sp)
4865
542
#define emptystack()  (sp == stack)
4866
4867
542
  som_initialize_reloc_queue (reloc_queue);
4868
542
  memset (variables, 0, sizeof (variables));
4869
542
  memset (stack, 0, sizeof (stack));
4870
542
  count = 0;
4871
542
  prev_fixup = 0;
4872
542
  saved_unwind_bits = 0;
4873
542
  sp = stack;
4874
4875
81.9k
  while (fixup < end_fixups)
4876
81.4k
    {
4877
81.4k
      const char *cp;
4878
81.4k
      unsigned int op;
4879
81.4k
      const struct fixup_format *fp;
4880
4881
      /* Save pointer to the start of this fixup.  We'll use
4882
   it later to determine if it is necessary to put this fixup
4883
   on the queue.  */
4884
81.4k
      unsigned char *save_fixup = fixup;
4885
4886
      /* Get the fixup code and its associated format.  */
4887
81.4k
      op = *fixup++;
4888
81.4k
      fp = &som_fixup_formats[op];
4889
4890
      /* Handle a request for a previous fixup.  */
4891
81.4k
      if (*fp->format == 'P')
4892
11.7k
  {
4893
11.7k
    if (!reloc_queue[fp->D].reloc)
4894
      /* The back-reference doesn't exist.  This is a broken
4895
         object file, likely fuzzed.  Just ignore the fixup.  */
4896
786
      continue;
4897
4898
    /* Get pointer to the beginning of the prev fixup, move
4899
       the repeated fixup to the head of the queue.  */
4900
10.9k
    fixup = reloc_queue[fp->D].reloc;
4901
10.9k
    som_reloc_queue_fix (reloc_queue, fp->D);
4902
10.9k
    prev_fixup = 1;
4903
4904
    /* Get the fixup code and its associated format.  */
4905
10.9k
    op = *fixup++;
4906
10.9k
    fp = &som_fixup_formats[op];
4907
10.9k
  }
4908
4909
      /* If this fixup will be passed to BFD, set some reasonable defaults.  */
4910
80.6k
      if (! just_count
4911
80.6k
    && som_hppa_howto_table[op].type != R_NO_RELOCATION
4912
80.6k
    && som_hppa_howto_table[op].type != R_DATA_OVERRIDE)
4913
16.3k
  {
4914
16.3k
    rptr->address = offset;
4915
16.3k
    rptr->howto = &som_hppa_howto_table[op];
4916
16.3k
    rptr->addend = 0;
4917
16.3k
    rptr->sym_ptr_ptr = &bfd_abs_section_ptr->symbol;
4918
16.3k
  }
4919
4920
      /* Set default input length to 0.  Get the opcode class index
4921
   into D.  */
4922
80.6k
      var ('L') = 0;
4923
80.6k
      var ('D') = fp->D;
4924
80.6k
      var ('U') = saved_unwind_bits;
4925
4926
      /* Get the opcode format.  */
4927
80.6k
      cp = fp->format;
4928
4929
      /* Process the format string.  Parsing happens in two phases,
4930
   parse RHS, then assign to LHS.  Repeat until no more
4931
   characters in the format string.  */
4932
178k
      while (*cp)
4933
97.6k
  {
4934
    /* The variable this pass is going to compute a value for.  */
4935
97.6k
    unsigned int varname = *cp++;
4936
97.6k
    const int *subop;
4937
97.6k
    int c;
4938
4939
    /* Start processing RHS.  Continue until a NULL or '=' is found.  */
4940
97.6k
    do
4941
296k
      {
4942
296k
        unsigned v;
4943
4944
296k
        c = *cp++;
4945
4946
        /* If this is a variable, push it on the stack.  */
4947
296k
        if (ISUPPER (c))
4948
58.2k
    push (var (c));
4949
4950
        /* If this is a lower case letter, then it represents
4951
     additional data from the fixup stream to be pushed onto
4952
     the stack.  */
4953
238k
        else if (ISLOWER (c))
4954
24.1k
    {
4955
24.1k
      int bits = (c - 'a') * 8;
4956
66.0k
      for (v = 0; c > 'a' && fixup < end_fixups; --c)
4957
41.8k
        v = (v << 8) | *fixup++;
4958
24.1k
      if (varname == 'V')
4959
2.00k
        v = sign_extend (v, bits);
4960
24.1k
      push (v);
4961
24.1k
    }
4962
4963
        /* A decimal constant.  Push it on the stack.  */
4964
214k
        else if (ISDIGIT (c))
4965
114k
    {
4966
114k
      v = c - '0';
4967
114k
      while (ISDIGIT (*cp))
4968
1.18k
        v = (v * 10) + (*cp++ - '0');
4969
114k
      push (v);
4970
114k
    }
4971
99.4k
        else
4972
    /* An operator.  Pop two values from the stack and
4973
       use them as operands to the given operation.  Push
4974
       the result of the operation back on the stack.  */
4975
99.4k
    switch (c)
4976
99.4k
      {
4977
50.0k
      case '+':
4978
50.0k
        v = pop ();
4979
50.0k
        v += pop ();
4980
50.0k
        push (v);
4981
50.0k
        break;
4982
46.1k
      case '*':
4983
46.1k
        v = pop ();
4984
46.1k
        v *= pop ();
4985
46.1k
        push (v);
4986
46.1k
        break;
4987
3.24k
      case '<':
4988
3.24k
        v = pop ();
4989
3.24k
        v = pop () << v;
4990
3.24k
        push (v);
4991
3.24k
        break;
4992
0
      default:
4993
0
        abort ();
4994
99.4k
      }
4995
296k
      }
4996
296k
    while (*cp && *cp != '=');
4997
4998
    /* Move over the equal operator.  */
4999
97.6k
    cp++;
5000
5001
    /* Pop the RHS off the stack.  */
5002
97.6k
    c = pop ();
5003
5004
    /* Perform the assignment.  */
5005
97.6k
    var (varname) = c;
5006
5007
    /* Handle side effects. and special 'O' stack cases.  */
5008
97.6k
    switch (varname)
5009
97.6k
      {
5010
      /* Consume some bytes from the input space.  */
5011
63.7k
      case 'L':
5012
63.7k
        offset += c;
5013
63.7k
        break;
5014
      /* A symbol to use in the relocation.  Make a note
5015
         of this if we are not just counting.  */
5016
17.3k
      case 'S':
5017
17.3k
        if (!just_count && symbols != NULL && (unsigned int) c < symcount)
5018
1.62k
    rptr->sym_ptr_ptr = &symbols[c];
5019
17.3k
        break;
5020
      /* Argument relocation bits for a function call.  */
5021
9.26k
      case 'R':
5022
9.26k
        if (! just_count)
5023
4.41k
    {
5024
4.41k
      unsigned int tmp = var ('R');
5025
4.41k
      rptr->addend = 0;
5026
5027
4.41k
      if ((som_hppa_howto_table[op].type == R_PCREL_CALL
5028
4.41k
           && R_PCREL_CALL + 10 > op)
5029
4.41k
          || (som_hppa_howto_table[op].type == R_ABS_CALL
5030
2.36k
        && R_ABS_CALL + 10 > op))
5031
3.28k
        {
5032
          /* Simple encoding.  */
5033
3.28k
          if (tmp > 4)
5034
1.18k
      {
5035
1.18k
        tmp -= 5;
5036
1.18k
        rptr->addend |= 1;
5037
1.18k
      }
5038
3.28k
          if (tmp == 4)
5039
796
      rptr->addend |= 1 << 8 | 1 << 6 | 1 << 4 | 1 << 2;
5040
2.48k
          else if (tmp == 3)
5041
304
      rptr->addend |= 1 << 8 | 1 << 6 | 1 << 4;
5042
2.18k
          else if (tmp == 2)
5043
779
      rptr->addend |= 1 << 8 | 1 << 6;
5044
1.40k
          else if (tmp == 1)
5045
654
      rptr->addend |= 1 << 8;
5046
3.28k
        }
5047
1.13k
      else
5048
1.13k
        {
5049
1.13k
          unsigned int tmp1, tmp2;
5050
5051
          /* First part is easy -- low order two bits are
5052
       directly copied, then shifted away.  */
5053
1.13k
          rptr->addend = tmp & 0x3;
5054
1.13k
          tmp >>= 2;
5055
5056
          /* Diving the result by 10 gives us the second
5057
       part.  If it is 9, then the first two words
5058
       are a double precision paramater, else it is
5059
       3 * the first arg bits + the 2nd arg bits.  */
5060
1.13k
          tmp1 = tmp / 10;
5061
1.13k
          tmp -= tmp1 * 10;
5062
1.13k
          if (tmp1 == 9)
5063
104
      rptr->addend += (0xe << 6);
5064
1.03k
          else
5065
1.03k
      {
5066
        /* Get the two pieces.  */
5067
1.03k
        tmp2 = tmp1 / 3;
5068
1.03k
        tmp1 -= tmp2 * 3;
5069
        /* Put them in the addend.  */
5070
1.03k
        rptr->addend += (tmp2 << 8) + (tmp1 << 6);
5071
1.03k
      }
5072
5073
          /* What's left is the third part.  It's unpacked
5074
       just like the second.  */
5075
1.13k
          if (tmp == 9)
5076
125
      rptr->addend += (0xe << 2);
5077
1.01k
          else
5078
1.01k
      {
5079
1.01k
        tmp2 = tmp / 3;
5080
1.01k
        tmp -= tmp2 * 3;
5081
1.01k
        rptr->addend += (tmp2 << 4) + (tmp << 2);
5082
1.01k
      }
5083
1.13k
        }
5084
4.41k
      rptr->addend = HPPA_R_ADDEND (rptr->addend, 0);
5085
4.41k
    }
5086
9.26k
        break;
5087
      /* Handle the linker expression stack.  */
5088
1.02k
      case 'O':
5089
1.02k
        switch (op)
5090
1.02k
    {
5091
759
    case R_COMP1:
5092
759
      subop = comp1_opcodes;
5093
759
      break;
5094
98
    case R_COMP2:
5095
98
      subop = comp2_opcodes;
5096
98
      break;
5097
167
    case R_COMP3:
5098
167
      subop = comp3_opcodes;
5099
167
      break;
5100
0
    default:
5101
0
      abort ();
5102
1.02k
    }
5103
36.6k
        while (*subop <= (unsigned char) c)
5104
35.6k
    ++subop;
5105
1.02k
        --subop;
5106
1.02k
        break;
5107
      /* The lower 32unwind bits must be persistent.  */
5108
942
      case 'U':
5109
942
        saved_unwind_bits = var ('U');
5110
942
        break;
5111
5112
5.23k
      default:
5113
5.23k
        break;
5114
97.6k
      }
5115
97.6k
  }
5116
5117
      /* If we used a previous fixup, clean up after it.  */
5118
80.6k
      if (prev_fixup)
5119
10.9k
  {
5120
10.9k
    fixup = save_fixup + 1;
5121
10.9k
    prev_fixup = 0;
5122
10.9k
  }
5123
      /* Queue it.  */
5124
69.7k
      else if (fixup > save_fixup + 1)
5125
9.43k
  som_reloc_queue_insert (save_fixup, fixup - save_fixup, reloc_queue);
5126
5127
      /* We do not pass R_DATA_OVERRIDE or R_NO_RELOCATION
5128
   fixups to BFD.  */
5129
80.6k
      if (som_hppa_howto_table[op].type != R_DATA_OVERRIDE
5130
80.6k
    && som_hppa_howto_table[op].type != R_NO_RELOCATION)
5131
34.6k
  {
5132
    /* Done with a single reloction. Loop back to the top.  */
5133
34.6k
    if (! just_count)
5134
16.3k
      {
5135
16.3k
        if (som_hppa_howto_table[op].type == R_ENTRY)
5136
461
    rptr->addend = var ('T');
5137
15.8k
        else if (som_hppa_howto_table[op].type == R_EXIT)
5138
217
    rptr->addend = var ('U');
5139
15.6k
        else if (som_hppa_howto_table[op].type == R_PCREL_CALL
5140
15.6k
           || som_hppa_howto_table[op].type == R_ABS_CALL)
5141
4.08k
    ;
5142
11.5k
        else if (som_hppa_howto_table[op].type == R_DATA_ONE_SYMBOL)
5143
933
    {
5144
      /* Try what was specified in R_DATA_OVERRIDE first
5145
         (if anything).  Then the hard way using the
5146
         section contents.  */
5147
933
      rptr->addend = var ('V');
5148
5149
933
      if (rptr->addend == 0
5150
933
          && (section->flags & SEC_HAS_CONTENTS) != 0)
5151
537
        {
5152
537
          if (!section->contents)
5153
153
      {
5154
        /* Got to read the damn contents first.  We don't
5155
           bother saving the contents (yet).  Add it one
5156
           day if the need arises.  */
5157
153
        bfd_byte *contents;
5158
153
        if (!bfd_malloc_and_get_section (section->owner,
5159
153
                 section, &contents))
5160
69
          {
5161
69
            free (contents);
5162
69
            return (unsigned) -1;
5163
69
          }
5164
84
        section->contents = contents;
5165
84
        deallocate_contents = 1;
5166
84
      }
5167
468
          if (offset - var ('L') <= section->size
5168
468
        && section->size - (offset - var ('L')) >= 4)
5169
83
      rptr->addend = bfd_get_32 (section->owner,
5170
468
               (section->contents
5171
468
                + offset - var ('L')));
5172
468
        }
5173
933
    }
5174
10.6k
        else
5175
10.6k
    rptr->addend = var ('V');
5176
16.2k
        rptr++;
5177
16.2k
      }
5178
34.5k
    count++;
5179
    /* Now that we've handled a "full" relocation, reset
5180
       some state.  */
5181
34.5k
    memset (variables, 0, sizeof (variables));
5182
34.5k
    memset (stack, 0, sizeof (stack));
5183
34.5k
  }
5184
80.6k
    }
5185
473
  if (deallocate_contents)
5186
84
    {
5187
84
      free (section->contents);
5188
84
      section->contents = NULL;
5189
84
    }
5190
5191
473
  return count;
5192
5193
542
#undef var
5194
542
#undef push
5195
542
#undef pop
5196
542
#undef emptystack
5197
542
}
5198
5199
/* Read in the relocs (aka fixups in SOM terms) for a section.
5200
5201
   som_get_reloc_upper_bound calls this routine with JUST_COUNT
5202
   set to TRUE to indicate it only needs a count of the number
5203
   of actual relocations.  */
5204
5205
static bool
5206
som_slurp_reloc_table (bfd *abfd,
5207
           asection *section,
5208
           asymbol **symbols,
5209
           bool just_count)
5210
932
{
5211
932
  unsigned char *external_relocs;
5212
932
  unsigned int fixup_stream_size;
5213
932
  arelent *internal_relocs;
5214
932
  unsigned int num_relocs;
5215
932
  size_t amt;
5216
5217
932
  fixup_stream_size = som_section_data (section)->reloc_size;
5218
  /* If there were no relocations, then there is nothing to do.  */
5219
932
  if (section->reloc_count == 0)
5220
8
    return true;
5221
5222
  /* If reloc_count is -1, then the relocation stream has not been
5223
     parsed.  We must do so now to know how many relocations exist.  */
5224
924
  if (section->reloc_count == (unsigned) -1)
5225
657
    {
5226
      /* Read in the external forms.  */
5227
657
      if (bfd_seek (abfd, obj_som_reloc_filepos (abfd) + section->rel_filepos,
5228
657
        SEEK_SET) != 0)
5229
4
  return false;
5230
653
      amt = fixup_stream_size;
5231
653
      external_relocs = _bfd_malloc_and_read (abfd, amt, amt);
5232
653
      if (external_relocs == NULL)
5233
378
  return false;
5234
5235
      /* Let callers know how many relocations found.
5236
   also save the relocation stream as we will
5237
   need it again.  */
5238
275
      section->reloc_count = som_set_reloc_info (external_relocs,
5239
275
             fixup_stream_size,
5240
275
             NULL, NULL, NULL, 0, true);
5241
5242
275
      som_section_data (section)->reloc_stream = external_relocs;
5243
275
    }
5244
5245
  /* If the caller only wanted a count, then return now.  */
5246
542
  if (just_count)
5247
275
    return true;
5248
5249
267
  num_relocs = section->reloc_count;
5250
267
  external_relocs = som_section_data (section)->reloc_stream;
5251
  /* Return saved information about the relocations if it is available.  */
5252
267
  if (section->relocation != NULL)
5253
0
    return true;
5254
5255
267
  if (_bfd_mul_overflow (num_relocs, sizeof (arelent), &amt))
5256
0
    {
5257
0
      bfd_set_error (bfd_error_file_too_big);
5258
0
      return false;
5259
0
    }
5260
267
  internal_relocs = bfd_zalloc (abfd, amt);
5261
267
  if (internal_relocs == NULL)
5262
0
    return false;
5263
5264
  /* Process and internalize the relocations.  */
5265
267
  som_set_reloc_info (external_relocs, fixup_stream_size,
5266
267
          internal_relocs, section, symbols,
5267
267
          bfd_get_symcount (abfd), false);
5268
5269
  /* We're done with the external relocations.  Free them.  */
5270
267
  free (external_relocs);
5271
267
  som_section_data (section)->reloc_stream = NULL;
5272
5273
  /* Save our results and return success.  */
5274
267
  section->relocation = internal_relocs;
5275
267
  return true;
5276
267
}
5277
5278
/* Return the number of bytes required to store the relocation
5279
   information associated with the given section.  */
5280
5281
static long
5282
som_get_reloc_upper_bound (bfd *abfd, sec_ptr asect)
5283
657
{
5284
  /* If section has relocations, then read in the relocation stream
5285
     and parse it to determine how many relocations exist.  */
5286
657
  if (asect->flags & SEC_RELOC)
5287
657
    {
5288
657
      if (! som_slurp_reloc_table (abfd, asect, NULL, true))
5289
382
  return -1;
5290
275
      return (asect->reloc_count + 1) * sizeof (arelent *);
5291
657
    }
5292
5293
  /* There are no relocations.  Return enough space to hold the
5294
     NULL pointer which will be installed if som_canonicalize_reloc
5295
     is called.  */
5296
0
  return sizeof (arelent *);
5297
657
}
5298
5299
/* Convert relocations from SOM (external) form into BFD internal
5300
   form.  Return the number of relocations.  */
5301
5302
static long
5303
som_canonicalize_reloc (bfd *abfd,
5304
      sec_ptr section,
5305
      arelent **relptr,
5306
      asymbol **symbols)
5307
275
{
5308
275
  arelent *tblptr;
5309
275
  int count;
5310
5311
275
  if (! som_slurp_reloc_table (abfd, section, symbols, false))
5312
0
    return -1;
5313
5314
275
  count = section->reloc_count;
5315
275
  tblptr = section->relocation;
5316
5317
18.6k
  while (count--)
5318
18.3k
    *relptr++ = tblptr++;
5319
5320
275
  *relptr = NULL;
5321
275
  return section->reloc_count;
5322
275
}
5323
5324
extern const bfd_target hppa_som_vec;
5325
5326
/* A hook to set up object file dependent section information.  */
5327
5328
static bool
5329
som_new_section_hook (bfd *abfd, asection *newsect)
5330
80.1k
{
5331
80.1k
  size_t amt = sizeof (struct som_section_data_struct);
5332
5333
80.1k
  newsect->used_by_bfd = bfd_zalloc (abfd, amt);
5334
80.1k
  if (!newsect->used_by_bfd)
5335
0
    return false;
5336
5337
80.1k
  newsect->alignment_power = 3;
5338
5339
  /* We allow more than three sections internally.  */
5340
80.1k
  return _bfd_generic_new_section_hook (abfd, newsect);
5341
80.1k
}
5342
5343
/* Copy any private info we understand from the input symbol
5344
   to the output symbol.  */
5345
5346
static bool
5347
som_bfd_copy_private_symbol_data (bfd *ibfd,
5348
          asymbol *isymbol,
5349
          bfd *obfd,
5350
          asymbol *osymbol)
5351
0
{
5352
0
  struct som_symbol *input_symbol = (struct som_symbol *) isymbol;
5353
0
  struct som_symbol *output_symbol = (struct som_symbol *) osymbol;
5354
5355
  /* One day we may try to grok other private data.  */
5356
0
  if (ibfd->xvec->flavour != bfd_target_som_flavour
5357
0
      || obfd->xvec->flavour != bfd_target_som_flavour)
5358
0
    return false;
5359
5360
  /* The only private information we need to copy is the argument relocation
5361
     bits.  */
5362
0
  output_symbol->tc_data.ap.hppa_arg_reloc =
5363
0
    input_symbol->tc_data.ap.hppa_arg_reloc;
5364
5365
0
  return true;
5366
0
}
5367
5368
/* Copy any private info we understand from the input section
5369
   to the output section.  */
5370
5371
static bool
5372
som_bfd_copy_private_section_data (bfd *ibfd,
5373
           asection *isection,
5374
           bfd *obfd,
5375
           asection *osection)
5376
0
{
5377
0
  size_t amt;
5378
5379
  /* One day we may try to grok other private data.  */
5380
0
  if (ibfd->xvec->flavour != bfd_target_som_flavour
5381
0
      || obfd->xvec->flavour != bfd_target_som_flavour
5382
0
      || (!som_is_space (isection) && !som_is_subspace (isection)))
5383
0
    return true;
5384
5385
0
  amt = sizeof (struct som_copyable_section_data_struct);
5386
0
  som_section_data (osection)->copy_data = bfd_zalloc (obfd, amt);
5387
0
  if (som_section_data (osection)->copy_data == NULL)
5388
0
    return false;
5389
5390
0
  memcpy (som_section_data (osection)->copy_data,
5391
0
    som_section_data (isection)->copy_data,
5392
0
    sizeof (struct som_copyable_section_data_struct));
5393
5394
  /* Reparent if necessary.  */
5395
0
  if (som_section_data (osection)->copy_data->container)
5396
0
    {
5397
0
      if (som_section_data (osection)->copy_data->container->output_section)
5398
0
  som_section_data (osection)->copy_data->container =
5399
0
    som_section_data (osection)->copy_data->container->output_section;
5400
0
      else
5401
0
  {
5402
    /* User has specified a subspace without its containing space.  */
5403
0
    _bfd_error_handler (_("%pB[%pA]: no output section for space %pA"),
5404
0
      obfd, osection, som_section_data (osection)->copy_data->container);
5405
0
    return false;
5406
0
  }
5407
0
    }
5408
5409
0
  return true;
5410
0
}
5411
5412
/* Copy any private info we understand from the input bfd
5413
   to the output bfd.  */
5414
5415
static bool
5416
som_bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
5417
0
{
5418
  /* One day we may try to grok other private data.  */
5419
0
  if (ibfd->xvec->flavour != bfd_target_som_flavour
5420
0
      || obfd->xvec->flavour != bfd_target_som_flavour)
5421
0
    return true;
5422
5423
  /* Allocate some memory to hold the data we need.  */
5424
0
  obj_som_exec_data (obfd) = bfd_zalloc (obfd, (bfd_size_type) sizeof (struct som_exec_data));
5425
0
  if (obj_som_exec_data (obfd) == NULL)
5426
0
    return false;
5427
5428
  /* Now copy the data.  */
5429
0
  memcpy (obj_som_exec_data (obfd), obj_som_exec_data (ibfd),
5430
0
    sizeof (struct som_exec_data));
5431
5432
0
  return true;
5433
0
}
5434
5435
/* Display the SOM header.  */
5436
5437
static bool
5438
som_bfd_print_private_bfd_data (bfd *abfd, void *farg)
5439
143
{
5440
143
  struct som_exec_auxhdr *exec_header;
5441
143
  struct som_aux_id* auxhdr;
5442
143
  FILE *f;
5443
5444
143
  f = (FILE *) farg;
5445
5446
143
  exec_header = obj_som_exec_hdr (abfd);
5447
143
  if (exec_header)
5448
132
    {
5449
132
      fprintf (f, _("\nExec Auxiliary Header\n"));
5450
132
      fprintf (f, "  flags              ");
5451
132
      auxhdr = &exec_header->som_auxhdr;
5452
132
      if (auxhdr->mandatory)
5453
25
  fprintf (f, "mandatory ");
5454
132
      if (auxhdr->copy)
5455
23
  fprintf (f, "copy ");
5456
132
      if (auxhdr->append)
5457
35
  fprintf (f, "append ");
5458
132
      if (auxhdr->ignore)
5459
33
  fprintf (f, "ignore ");
5460
132
      fprintf (f, "\n");
5461
132
      fprintf (f, "  type               %#x\n", auxhdr->type);
5462
132
      fprintf (f, "  length             %#x\n", auxhdr->length);
5463
5464
      /* Note that, depending on the HP-UX version, the following fields can be
5465
   either ints, or longs.  */
5466
5467
132
      fprintf (f, "  text size          %#lx\n", (long) exec_header->exec_tsize);
5468
132
      fprintf (f, "  text memory offset %#lx\n", (long) exec_header->exec_tmem);
5469
132
      fprintf (f, "  text file offset   %#lx\n", (long) exec_header->exec_tfile);
5470
132
      fprintf (f, "  data size          %#lx\n", (long) exec_header->exec_dsize);
5471
132
      fprintf (f, "  data memory offset %#lx\n", (long) exec_header->exec_dmem);
5472
132
      fprintf (f, "  data file offset   %#lx\n", (long) exec_header->exec_dfile);
5473
132
      fprintf (f, "  bss size           %#lx\n", (long) exec_header->exec_bsize);
5474
132
      fprintf (f, "  entry point        %#lx\n", (long) exec_header->exec_entry);
5475
132
      fprintf (f, "  loader flags       %#lx\n", (long) exec_header->exec_flags);
5476
132
      fprintf (f, "  bss initializer    %#lx\n", (long) exec_header->exec_bfill);
5477
132
    }
5478
5479
143
  return true;
5480
143
}
5481
5482
/* Set backend info for sections which can not be described
5483
   in the BFD data structures.  */
5484
5485
bool
5486
bfd_som_set_section_attributes (asection *section,
5487
        int defined,
5488
        int private,
5489
        unsigned int sort_key,
5490
        int spnum)
5491
32.2k
{
5492
  /* Allocate memory to hold the magic information.  */
5493
32.2k
  if (som_section_data (section)->copy_data == NULL)
5494
32.2k
    {
5495
32.2k
      size_t amt = sizeof (struct som_copyable_section_data_struct);
5496
5497
32.2k
      som_section_data (section)->copy_data = bfd_zalloc (section->owner, amt);
5498
32.2k
      if (som_section_data (section)->copy_data == NULL)
5499
0
  return false;
5500
32.2k
    }
5501
32.2k
  som_section_data (section)->copy_data->sort_key = sort_key;
5502
32.2k
  som_section_data (section)->copy_data->is_defined = defined;
5503
32.2k
  som_section_data (section)->copy_data->is_private = private;
5504
32.2k
  som_section_data (section)->copy_data->container = section;
5505
32.2k
  som_section_data (section)->copy_data->space_number = spnum;
5506
32.2k
  return true;
5507
32.2k
}
5508
5509
/* Set backend info for subsections which can not be described
5510
   in the BFD data structures.  */
5511
5512
bool
5513
bfd_som_set_subsection_attributes (asection *section,
5514
           asection *container,
5515
           int access_ctr,
5516
           unsigned int sort_key,
5517
           int quadrant,
5518
           int comdat,
5519
           int common,
5520
           int dup_common)
5521
47.8k
{
5522
  /* Allocate memory to hold the magic information.  */
5523
47.8k
  if (som_section_data (section)->copy_data == NULL)
5524
47.8k
    {
5525
47.8k
      size_t amt = sizeof (struct som_copyable_section_data_struct);
5526
5527
47.8k
      som_section_data (section)->copy_data = bfd_zalloc (section->owner, amt);
5528
47.8k
      if (som_section_data (section)->copy_data == NULL)
5529
0
  return false;
5530
47.8k
    }
5531
47.8k
  som_section_data (section)->copy_data->sort_key = sort_key;
5532
47.8k
  som_section_data (section)->copy_data->access_control_bits = access_ctr;
5533
47.8k
  som_section_data (section)->copy_data->quadrant = quadrant;
5534
47.8k
  som_section_data (section)->copy_data->container = container;
5535
47.8k
  som_section_data (section)->copy_data->is_comdat = comdat;
5536
47.8k
  som_section_data (section)->copy_data->is_common = common;
5537
47.8k
  som_section_data (section)->copy_data->dup_common = dup_common;
5538
47.8k
  return true;
5539
47.8k
}
5540
5541
/* Set the full SOM symbol type.  SOM needs far more symbol information
5542
   than any other object file format I'm aware of.  It is mandatory
5543
   to be able to know if a symbol is an entry point, millicode, data,
5544
   code, absolute, storage request, or procedure label.  If you get
5545
   the symbol type wrong your program will not link.  */
5546
5547
void
5548
bfd_som_set_symbol_type (asymbol *symbol, unsigned int type)
5549
0
{
5550
0
  som_symbol_data (symbol)->som_type = type;
5551
0
}
5552
5553
/* Attach an auxiliary header to the BFD backend so that it may be
5554
   written into the object file.  */
5555
5556
bool
5557
bfd_som_attach_aux_hdr (bfd *abfd, int type, char *string)
5558
0
{
5559
0
  size_t amt;
5560
5561
0
  if (type == VERSION_AUX_ID)
5562
0
    {
5563
0
      size_t len = strlen (string);
5564
0
      int pad = 0;
5565
5566
0
      if (len % 4)
5567
0
  pad = (4 - (len % 4));
5568
0
      amt = sizeof (struct som_string_auxhdr) + len + pad;
5569
0
      obj_som_version_hdr (abfd) = bfd_zalloc (abfd, amt);
5570
0
      if (!obj_som_version_hdr (abfd))
5571
0
  return false;
5572
0
      obj_som_version_hdr (abfd)->header_id.type = VERSION_AUX_ID;
5573
0
      obj_som_version_hdr (abfd)->header_id.length = 4 + len + pad;
5574
0
      obj_som_version_hdr (abfd)->string_length = len;
5575
0
      memcpy (obj_som_version_hdr (abfd)->string, string, len);
5576
0
      memset (obj_som_version_hdr (abfd)->string + len, 0, pad);
5577
0
    }
5578
0
  else if (type == COPYRIGHT_AUX_ID)
5579
0
    {
5580
0
      size_t len = strlen (string);
5581
0
      int pad = 0;
5582
5583
0
      if (len % 4)
5584
0
  pad = (4 - (len % 4));
5585
0
      amt = sizeof (struct som_string_auxhdr) + len + pad;
5586
0
      obj_som_copyright_hdr (abfd) = bfd_zalloc (abfd, amt);
5587
0
      if (!obj_som_copyright_hdr (abfd))
5588
0
  return false;
5589
0
      obj_som_copyright_hdr (abfd)->header_id.type = COPYRIGHT_AUX_ID;
5590
0
      obj_som_copyright_hdr (abfd)->header_id.length = len + pad + 4;
5591
0
      obj_som_copyright_hdr (abfd)->string_length = len;
5592
0
      memcpy (obj_som_copyright_hdr (abfd)->string, string, len);
5593
0
      memset (obj_som_copyright_hdr (abfd)->string + len, 0, pad);
5594
0
    }
5595
0
  return true;
5596
0
}
5597
5598
/* Attach a compilation unit header to the BFD backend so that it may be
5599
   written into the object file.  */
5600
5601
bool
5602
bfd_som_attach_compilation_unit (bfd *abfd,
5603
         const char *name,
5604
         const char *language_name,
5605
         const char *product_id,
5606
         const char *version_id)
5607
0
{
5608
0
  struct som_compilation_unit *n;
5609
5610
0
  n = (struct som_compilation_unit *) bfd_zalloc
5611
0
    (abfd, (bfd_size_type) sizeof (*n));
5612
0
  if (n == NULL)
5613
0
    return false;
5614
5615
0
#define STRDUP(f) \
5616
0
  if (f != NULL) \
5617
0
    { \
5618
0
      n->f.name = bfd_alloc (abfd, (bfd_size_type) strlen (f) + 1); \
5619
0
      if (n->f.name == NULL) \
5620
0
  return false; \
5621
0
      strcpy (n->f.name, f); \
5622
0
    }
5623
5624
0
  STRDUP (name);
5625
0
  STRDUP (language_name);
5626
0
  STRDUP (product_id);
5627
0
  STRDUP (version_id);
5628
5629
0
#undef STRDUP
5630
5631
0
  obj_som_compilation_unit (abfd) = n;
5632
5633
0
  return true;
5634
0
}
5635
5636
static bool
5637
som_get_section_contents (bfd *abfd,
5638
        sec_ptr section,
5639
        void *location,
5640
        file_ptr offset,
5641
        bfd_size_type count)
5642
2.64k
{
5643
2.64k
  if (count == 0 || ((section->flags & SEC_HAS_CONTENTS) == 0))
5644
0
    return true;
5645
2.64k
  if ((bfd_size_type) (offset + count) > section->size
5646
2.64k
      || bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0
5647
2.64k
      || bfd_read (location, count, abfd) != count)
5648
685
    return false; /* On error.  */
5649
1.95k
  return true;
5650
2.64k
}
5651
5652
static bool
5653
som_set_section_contents (bfd *abfd,
5654
        sec_ptr section,
5655
        const void *location,
5656
        file_ptr offset,
5657
        bfd_size_type count)
5658
0
{
5659
0
  if (! abfd->output_has_begun)
5660
0
    {
5661
      /* Set up fixed parts of the file, space, and subspace headers.
5662
   Notify the world that output has begun.  */
5663
0
      som_prep_headers (abfd);
5664
0
      abfd->output_has_begun = true;
5665
      /* Start writing the object file.  This include all the string
5666
   tables, fixup streams, and other portions of the object file.  */
5667
0
      som_begin_writing (abfd);
5668
0
    }
5669
5670
  /* Only write subspaces which have "real" contents (eg. the contents
5671
     are not generated at run time by the OS).  */
5672
0
  if (!som_is_subspace (section)
5673
0
      || ((section->flags & SEC_HAS_CONTENTS) == 0))
5674
0
    return true;
5675
5676
  /* Seek to the proper offset within the object file and write the
5677
     data.  */
5678
0
  offset += som_section_data (section)->subspace_dict->file_loc_init_value;
5679
0
  if (bfd_seek (abfd, offset, SEEK_SET) != 0)
5680
0
    return false;
5681
5682
0
  if (bfd_write (location, count, abfd) != count)
5683
0
    return false;
5684
0
  return true;
5685
0
}
5686
5687
static bool
5688
som_set_arch_mach (bfd *abfd,
5689
       enum bfd_architecture arch,
5690
       unsigned long machine)
5691
0
{
5692
  /* Allow any architecture to be supported by the SOM backend.  */
5693
0
  return bfd_default_set_arch_mach (abfd, arch, machine);
5694
0
}
5695
5696
static bool
5697
som_find_nearest_line (bfd *abfd,
5698
           asymbol **symbols,
5699
           asection *section,
5700
           bfd_vma offset,
5701
           const char **filename_ptr,
5702
           const char **functionname_ptr,
5703
           unsigned int *line_ptr,
5704
           unsigned int *discriminator_ptr)
5705
2.02k
{
5706
2.02k
  bool found;
5707
2.02k
  asymbol *func;
5708
2.02k
  bfd_vma low_func;
5709
2.02k
  asymbol **p;
5710
5711
2.02k
  if (discriminator_ptr)
5712
554
    *discriminator_ptr = 0;
5713
5714
2.02k
  if (! _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset,
5715
2.02k
               & found, filename_ptr,
5716
2.02k
               functionname_ptr, line_ptr,
5717
2.02k
               & somdata (abfd).line_info))
5718
0
    return false;
5719
5720
2.02k
  if (found)
5721
0
    return true;
5722
5723
2.02k
  if (symbols == NULL)
5724
554
    return false;
5725
5726
  /* Fallback: find function name from symbols table.  */
5727
1.47k
  func = NULL;
5728
1.47k
  low_func = 0;
5729
5730
6.64k
  for (p = symbols; *p != NULL; p++)
5731
5.16k
    {
5732
5.16k
      som_symbol_type *q = (som_symbol_type *) *p;
5733
5734
5.16k
      if (q->som_type == SYMBOL_TYPE_ENTRY
5735
5.16k
    && q->symbol.section == section
5736
5.16k
    && q->symbol.value >= low_func
5737
5.16k
    && q->symbol.value <= offset)
5738
48
  {
5739
48
    func = (asymbol *) q;
5740
48
    low_func = q->symbol.value;
5741
48
  }
5742
5.16k
    }
5743
5744
1.47k
  if (func == NULL)
5745
1.42k
    return false;
5746
5747
47
  *filename_ptr = NULL;
5748
47
  *functionname_ptr = bfd_asymbol_name (func);
5749
47
  *line_ptr = 0;
5750
5751
47
  return true;
5752
1.47k
}
5753
5754
static int
5755
som_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
5756
        struct bfd_link_info *info ATTRIBUTE_UNUSED)
5757
0
{
5758
0
  _bfd_error_handler (_("som_sizeof_headers unimplemented"));
5759
0
  abort ();
5760
0
  return 0;
5761
0
}
5762
5763
/* Return the single-character symbol type corresponding to
5764
   SOM section S, or '?' for an unknown SOM section.  */
5765
5766
static char
5767
som_section_type (const char *s)
5768
73
{
5769
73
  const struct section_to_type *t;
5770
5771
1.38k
  for (t = &stt[0]; t->section; t++)
5772
1.31k
    if (!strcmp (s, t->section))
5773
0
      return t->type;
5774
73
  return '?';
5775
73
}
5776
5777
static int
5778
som_decode_symclass (asymbol *symbol)
5779
3.39k
{
5780
3.39k
  char c;
5781
5782
  /* If the symbol did not have a scope specified,
5783
     then it will not have associated section.  */
5784
3.39k
  if (symbol == NULL || symbol->section == NULL)
5785
0
    return '?';
5786
5787
3.39k
  if (bfd_is_com_section (symbol->section))
5788
36
    return 'C';
5789
3.35k
  if (bfd_is_und_section (symbol->section))
5790
3.11k
    {
5791
3.11k
      if (symbol->flags & BSF_WEAK)
5792
140
  {
5793
    /* If weak, determine if it's specifically an object
5794
       or non-object weak.  */
5795
140
    if (symbol->flags & BSF_OBJECT)
5796
0
      return 'v';
5797
140
    else
5798
140
      return 'w';
5799
140
  }
5800
2.97k
      else
5801
2.97k
   return 'U';
5802
3.11k
    }
5803
239
  if (bfd_is_ind_section (symbol->section))
5804
0
    return 'I';
5805
239
  if (symbol->flags & BSF_WEAK)
5806
53
    {
5807
      /* If weak, determine if it's specifically an object
5808
   or non-object weak.  */
5809
53
      if (symbol->flags & BSF_OBJECT)
5810
0
  return 'V';
5811
53
      else
5812
53
  return 'W';
5813
53
    }
5814
186
  if (!(symbol->flags & (BSF_GLOBAL | BSF_LOCAL)))
5815
0
    return '?';
5816
5817
186
  if (bfd_is_abs_section (symbol->section)
5818
186
      || (som_symbol_data (symbol) != NULL
5819
73
    && som_symbol_data (symbol)->som_type == SYMBOL_TYPE_ABSOLUTE))
5820
113
    c = 'a';
5821
73
  else if (symbol->section)
5822
73
    c = som_section_type (symbol->section->name);
5823
0
  else
5824
0
    return '?';
5825
186
  if (symbol->flags & BSF_GLOBAL)
5826
53
    c = TOUPPER (c);
5827
186
  return c;
5828
186
}
5829
5830
/* Return information about SOM symbol SYMBOL in RET.  */
5831
5832
static void
5833
som_get_symbol_info (bfd *ignore_abfd ATTRIBUTE_UNUSED,
5834
         asymbol *symbol,
5835
         symbol_info *ret)
5836
3.39k
{
5837
3.39k
  ret->type = som_decode_symclass (symbol);
5838
3.39k
  if (ret->type != 'U')
5839
415
    ret->value = symbol->value + symbol->section->vma;
5840
2.97k
  else
5841
2.97k
    ret->value = 0;
5842
3.39k
  ret->name = symbol->name;
5843
3.39k
}
5844
5845
/* Count the number of symbols in the archive symbol table.  Necessary
5846
   so that we can allocate space for all the carsyms at once.  */
5847
5848
static bool
5849
som_bfd_count_ar_symbols (bfd *abfd,
5850
        struct som_lst_header *lst_header,
5851
        symindex *count)
5852
1.78k
{
5853
1.78k
  unsigned int i;
5854
1.78k
  unsigned char *hash_table;
5855
1.78k
  size_t amt;
5856
1.78k
  file_ptr lst_filepos;
5857
5858
1.78k
  lst_filepos = bfd_tell (abfd) - sizeof (struct som_external_lst_header);
5859
5860
  /* Read in the hash table.  The hash table is an array of 32-bit
5861
     file offsets which point to the hash chains.  */
5862
1.78k
  if (_bfd_mul_overflow (lst_header->hash_size, 4, &amt))
5863
0
    {
5864
0
      bfd_set_error (bfd_error_file_too_big);
5865
0
      return false;
5866
0
    }
5867
1.78k
  hash_table = _bfd_malloc_and_read (abfd, amt, amt);
5868
1.78k
  if (hash_table == NULL && lst_header->hash_size != 0)
5869
123
    goto error_return;
5870
5871
  /* Don't forget to initialize the counter!  */
5872
1.66k
  *count = 0;
5873
5874
  /* Walk each chain counting the number of symbols found on that particular
5875
     chain.  */
5876
3.87k
  for (i = 0; i < lst_header->hash_size; i++)
5877
2.36k
    {
5878
2.36k
      struct som_external_lst_symbol_record ext_lst_symbol;
5879
2.36k
      unsigned int hash_val = bfd_getb32 (hash_table + 4 * i);
5880
5881
      /* An empty chain has zero as it's file offset.  */
5882
2.36k
      if (hash_val == 0)
5883
1.57k
  continue;
5884
5885
      /* Seek to the first symbol in this hash chain.  */
5886
793
      if (bfd_seek (abfd, lst_filepos + hash_val, SEEK_SET) != 0)
5887
0
  goto error_return;
5888
5889
      /* Read in this symbol and update the counter.  */
5890
793
      amt = sizeof (ext_lst_symbol);
5891
793
      if (bfd_read (&ext_lst_symbol, amt, abfd) != amt)
5892
85
  goto error_return;
5893
5894
708
      (*count)++;
5895
5896
      /* Now iterate through the rest of the symbols on this chain.  */
5897
1.16k
      while (1)
5898
1.16k
  {
5899
1.16k
    unsigned int next_entry = bfd_getb32 (ext_lst_symbol.next_entry);
5900
5901
1.16k
    if (next_entry == 0)
5902
635
      break;
5903
5904
    /* Assume symbols on a chain are in increasing file offset
5905
       order.  Otherwise we can loop here with fuzzed input.  */
5906
525
    if (next_entry < hash_val + sizeof (ext_lst_symbol))
5907
8
      {
5908
8
        bfd_set_error (bfd_error_bad_value);
5909
8
        goto error_return;
5910
8
      }
5911
517
    hash_val = next_entry;
5912
5913
    /* Seek to the next symbol.  */
5914
517
    if (bfd_seek (abfd, lst_filepos + next_entry, SEEK_SET) != 0)
5915
0
      goto error_return;
5916
5917
    /* Read the symbol in and update the counter.  */
5918
517
    amt = sizeof (ext_lst_symbol);
5919
517
    if (bfd_read (&ext_lst_symbol, amt, abfd) != amt)
5920
65
      goto error_return;
5921
5922
452
    (*count)++;
5923
452
  }
5924
708
    }
5925
1.50k
  free (hash_table);
5926
1.50k
  return true;
5927
5928
281
 error_return:
5929
281
  free (hash_table);
5930
281
  return false;
5931
1.66k
}
5932
5933
/* Fill in the canonical archive symbols (SYMS) from the archive described
5934
   by ABFD and LST_HEADER.  */
5935
5936
static bool
5937
som_bfd_fill_in_ar_symbols (bfd *abfd,
5938
          struct som_lst_header *lst_header,
5939
          carsym **syms)
5940
1.50k
{
5941
1.50k
  unsigned int i;
5942
1.50k
  carsym *set = syms[0];
5943
1.50k
  unsigned char *hash_table;
5944
1.50k
  struct som_external_som_entry *som_dict = NULL;
5945
1.50k
  size_t amt;
5946
1.50k
  file_ptr lst_filepos;
5947
1.50k
  unsigned int string_loc;
5948
5949
1.50k
  lst_filepos = bfd_tell (abfd) - sizeof (struct som_external_lst_header);
5950
5951
  /* Read in the hash table.  The has table is an array of 32bit file offsets
5952
     which point to the hash chains.  */
5953
1.50k
  if (_bfd_mul_overflow (lst_header->hash_size, 4, &amt))
5954
0
    {
5955
0
      bfd_set_error (bfd_error_file_too_big);
5956
0
      return false;
5957
0
    }
5958
1.50k
  hash_table = _bfd_malloc_and_read (abfd, amt, amt);
5959
1.50k
  if (hash_table == NULL && lst_header->hash_size != 0)
5960
0
    goto error_return;
5961
5962
  /* Seek to and read in the SOM dictionary.  We will need this to fill
5963
     in the carsym's filepos field.  */
5964
1.50k
  if (bfd_seek (abfd, lst_filepos + lst_header->dir_loc, SEEK_SET) != 0)
5965
0
    goto error_return;
5966
5967
1.50k
  if (_bfd_mul_overflow (lst_header->module_count,
5968
1.50k
       sizeof (struct som_external_som_entry), &amt))
5969
0
    {
5970
0
      bfd_set_error (bfd_error_file_too_big);
5971
0
      goto error_return;
5972
0
    }
5973
1.50k
  som_dict = (struct som_external_som_entry *)
5974
1.50k
    _bfd_malloc_and_read (abfd, amt, amt);
5975
1.50k
  if (som_dict == NULL && lst_header->module_count != 0)
5976
98
    goto error_return;
5977
5978
1.40k
  string_loc = lst_header->string_loc;
5979
5980
  /* Walk each chain filling in the carsyms as we go along.  */
5981
2.37k
  for (i = 0; i < lst_header->hash_size; i++)
5982
1.16k
    {
5983
1.16k
      struct som_external_lst_symbol_record lst_symbol;
5984
1.16k
      unsigned int hash_val;
5985
1.16k
      size_t len;
5986
1.16k
      unsigned char ext_len[4];
5987
1.16k
      char *name;
5988
1.16k
      unsigned int ndx;
5989
5990
      /* An empty chain has zero as it's file offset.  */
5991
1.16k
      hash_val = bfd_getb32 (hash_table + 4 * i);
5992
1.16k
      if (hash_val == 0)
5993
809
  continue;
5994
5995
      /* Seek to and read the first symbol on the chain.  */
5996
353
      if (bfd_seek (abfd, lst_filepos + hash_val, SEEK_SET) != 0)
5997
0
  goto error_return;
5998
5999
353
      amt = sizeof (lst_symbol);
6000
353
      if (bfd_read (&lst_symbol, amt, abfd) != amt)
6001
0
  goto error_return;
6002
6003
      /* Get the name of the symbol, first get the length which is stored
6004
   as a 32bit integer just before the symbol.
6005
6006
   One might ask why we don't just read in the entire string table
6007
   and index into it.  Well, according to the SOM ABI the string
6008
   index can point *anywhere* in the archive to save space, so just
6009
   using the string table would not be safe.  */
6010
353
      if (bfd_seek (abfd, (lst_filepos + string_loc
6011
353
         + bfd_getb32 (lst_symbol.name) - 4), SEEK_SET) != 0)
6012
0
  goto error_return;
6013
6014
353
      if (bfd_read (&ext_len, 4, abfd) != 4)
6015
19
  goto error_return;
6016
334
      len = bfd_getb32 (ext_len);
6017
6018
      /* Allocate space for the name and null terminate it too.  */
6019
334
      if (len == (size_t) -1)
6020
0
  {
6021
0
    bfd_set_error (bfd_error_no_memory);
6022
0
    goto error_return;
6023
0
  }
6024
334
      name = (char *) _bfd_alloc_and_read (abfd, len + 1, len);
6025
334
      if (!name)
6026
79
  goto error_return;
6027
255
      name[len] = 0;
6028
255
      set->name = name;
6029
6030
      /* Fill in the file offset.  Note that the "location" field points
6031
   to the SOM itself, not the ar_hdr in front of it.  */
6032
255
      ndx = bfd_getb32 (lst_symbol.som_index);
6033
255
      if (ndx >= lst_header->module_count)
6034
17
  {
6035
17
    bfd_set_error (bfd_error_bad_value);
6036
17
    goto error_return;
6037
17
  }
6038
238
      set->file_offset
6039
238
  = bfd_getb32 (som_dict[ndx].location) - sizeof (struct ar_hdr);
6040
6041
      /* Go to the next symbol.  */
6042
238
      set++;
6043
6044
      /* Iterate through the rest of the chain.  */
6045
332
      while (1)
6046
332
  {
6047
332
    unsigned int next_entry = bfd_getb32 (lst_symbol.next_entry);
6048
6049
332
    if (next_entry == 0)
6050
158
      break;
6051
6052
    /* Seek to the next symbol and read it in.  */
6053
174
    if (bfd_seek (abfd, lst_filepos + next_entry, SEEK_SET) != 0)
6054
0
      goto error_return;
6055
6056
174
    amt = sizeof (lst_symbol);
6057
174
    if (bfd_read (&lst_symbol, amt, abfd) != amt)
6058
0
      goto error_return;
6059
6060
    /* Seek to the name length & string and read them in.  */
6061
174
    if (bfd_seek (abfd, lst_filepos + string_loc
6062
174
      + bfd_getb32 (lst_symbol.name) - 4, SEEK_SET) != 0)
6063
0
      goto error_return;
6064
6065
174
    if (bfd_read (&ext_len, 4, abfd) != 4)
6066
10
      goto error_return;
6067
164
    len = bfd_getb32 (ext_len);
6068
6069
    /* Allocate space for the name and null terminate it too.  */
6070
164
    if (len == (size_t) -1)
6071
0
      {
6072
0
        bfd_set_error (bfd_error_no_memory);
6073
0
        goto error_return;
6074
0
      }
6075
164
    name = (char *) _bfd_alloc_and_read (abfd, len + 1, len);
6076
164
    if (!name)
6077
63
      goto error_return;
6078
101
    name[len] = 0;
6079
101
    set->name = name;
6080
6081
    /* Fill in the file offset.  Note that the "location" field points
6082
       to the SOM itself, not the ar_hdr in front of it.  */
6083
101
    ndx = bfd_getb32 (lst_symbol.som_index);
6084
101
    if (ndx >= lst_header->module_count)
6085
7
      {
6086
7
        bfd_set_error (bfd_error_bad_value);
6087
7
        goto error_return;
6088
7
      }
6089
94
    set->file_offset
6090
94
      = bfd_getb32 (som_dict[ndx].location) - sizeof (struct ar_hdr);
6091
6092
    /* Go on to the next symbol.  */
6093
94
    set++;
6094
94
  }
6095
238
    }
6096
  /* If we haven't died by now, then we successfully read the entire
6097
     archive symbol table.  */
6098
1.21k
  free (hash_table);
6099
1.21k
  free (som_dict);
6100
1.21k
  return true;
6101
6102
293
 error_return:
6103
293
  free (hash_table);
6104
293
  free (som_dict);
6105
293
  return false;
6106
1.40k
}
6107
6108
/* Read in the LST from the archive.  */
6109
6110
static bool
6111
som_slurp_armap (bfd *abfd)
6112
47.2k
{
6113
47.2k
  struct som_external_lst_header ext_lst_header;
6114
47.2k
  struct som_lst_header lst_header;
6115
47.2k
  struct ar_hdr ar_header;
6116
47.2k
  unsigned int parsed_size;
6117
47.2k
  struct artdata *ardata = bfd_ardata (abfd);
6118
47.2k
  char nextname[17];
6119
47.2k
  size_t amt = 16;
6120
47.2k
  int i = bfd_read (nextname, amt, abfd);
6121
6122
  /* Special cases.  */
6123
47.2k
  if (i == 0)
6124
11
    return true;
6125
47.1k
  if (i != 16)
6126
32
    return false;
6127
6128
47.1k
  if (bfd_seek (abfd, -16, SEEK_CUR) != 0)
6129
0
    return false;
6130
6131
  /* For archives without .o files there is no symbol table.  */
6132
47.1k
  if (! startswith (nextname, "/               "))
6133
40.2k
    {
6134
40.2k
      abfd->has_armap = false;
6135
40.2k
      return true;
6136
40.2k
    }
6137
6138
  /* Read in and sanity check the archive header.  */
6139
6.88k
  amt = sizeof (struct ar_hdr);
6140
6.88k
  if (bfd_read (&ar_header, amt, abfd) != amt)
6141
13
    return false;
6142
6143
6.87k
  if (strncmp (ar_header.ar_fmag, ARFMAG, 2))
6144
1.64k
    {
6145
1.64k
      bfd_set_error (bfd_error_malformed_archive);
6146
1.64k
      return false;
6147
1.64k
    }
6148
6149
  /* How big is the archive symbol table entry?  */
6150
5.22k
  errno = 0;
6151
5.22k
  parsed_size = strtol (ar_header.ar_size, NULL, 10);
6152
5.22k
  if (errno != 0)
6153
0
    {
6154
0
      bfd_set_error (bfd_error_malformed_archive);
6155
0
      return false;
6156
0
    }
6157
6158
  /* Save off the file offset of the first real user data.  */
6159
5.22k
  ardata->first_file_filepos = bfd_tell (abfd) + parsed_size;
6160
6161
  /* Read in the library symbol table.  We'll make heavy use of this
6162
     in just a minute.  */
6163
5.22k
  amt = sizeof (struct som_external_lst_header);
6164
5.22k
  if (bfd_read (&ext_lst_header, amt, abfd) != amt)
6165
243
    return false;
6166
6167
4.98k
  som_swap_lst_header_in (&ext_lst_header, &lst_header);
6168
6169
  /* Sanity check.  */
6170
4.98k
  if (lst_header.a_magic != LIBMAGIC)
6171
3.19k
    {
6172
3.19k
      bfd_set_error (bfd_error_malformed_archive);
6173
3.19k
      return false;
6174
3.19k
    }
6175
6176
  /* Count the number of symbols in the library symbol table.  */
6177
1.78k
  if (! som_bfd_count_ar_symbols (abfd, &lst_header, &ardata->symdef_count))
6178
281
    return false;
6179
6180
  /* Get back to the start of the library symbol table.  */
6181
1.50k
  if (bfd_seek (abfd, (ardata->first_file_filepos - parsed_size
6182
1.50k
           + sizeof (struct som_external_lst_header)),
6183
1.50k
    SEEK_SET) != 0)
6184
0
    return false;
6185
6186
  /* Initialize the cache and allocate space for the library symbols.  */
6187
1.50k
  ardata->cache = 0;
6188
1.50k
  if (_bfd_mul_overflow (ardata->symdef_count, sizeof (carsym), &amt))
6189
0
    {
6190
0
      bfd_set_error (bfd_error_file_too_big);
6191
0
      return false;
6192
0
    }
6193
1.50k
  ardata->symdefs = bfd_alloc (abfd, amt);
6194
1.50k
  if (!ardata->symdefs)
6195
0
    return false;
6196
6197
  /* Now fill in the canonical archive symbols.  */
6198
1.50k
  if (! som_bfd_fill_in_ar_symbols (abfd, &lst_header, &ardata->symdefs))
6199
293
    return false;
6200
6201
  /* Seek back to the "first" file in the archive.  Note the "first"
6202
     file may be the extended name table.  */
6203
1.21k
  if (bfd_seek (abfd, ardata->first_file_filepos, SEEK_SET) != 0)
6204
0
    return false;
6205
6206
  /* Notify the generic archive code that we have a symbol map.  */
6207
1.21k
  abfd->has_armap = true;
6208
1.21k
  return true;
6209
1.21k
}
6210
6211
/* Begin preparing to write a SOM library symbol table.
6212
6213
   As part of the prep work we need to determine the number of symbols
6214
   and the size of the associated string section.  */
6215
6216
static bool
6217
som_bfd_prep_for_ar_write (bfd *abfd,
6218
         unsigned int *num_syms,
6219
         unsigned int *stringsize)
6220
0
{
6221
0
  bfd *curr_bfd = abfd->archive_head;
6222
6223
  /* Some initialization.  */
6224
0
  *num_syms = 0;
6225
0
  *stringsize = 0;
6226
6227
  /* Iterate over each BFD within this archive.  */
6228
0
  while (curr_bfd != NULL)
6229
0
    {
6230
0
      unsigned int curr_count, i;
6231
0
      som_symbol_type *sym;
6232
6233
      /* Don't bother for non-SOM objects.  */
6234
0
      if (curr_bfd->format != bfd_object
6235
0
    || curr_bfd->xvec->flavour != bfd_target_som_flavour)
6236
0
  {
6237
0
    curr_bfd = curr_bfd->archive_next;
6238
0
    continue;
6239
0
  }
6240
6241
      /* Make sure the symbol table has been read, then snag a pointer
6242
   to it.  It's a little slimey to grab the symbols via obj_som_symtab,
6243
   but doing so avoids allocating lots of extra memory.  */
6244
0
      if (! som_slurp_symbol_table (curr_bfd))
6245
0
  return false;
6246
6247
0
      sym = obj_som_symtab (curr_bfd);
6248
0
      curr_count = bfd_get_symcount (curr_bfd);
6249
6250
      /* Examine each symbol to determine if it belongs in the
6251
   library symbol table.  */
6252
0
      for (i = 0; i < curr_count; i++, sym++)
6253
0
  {
6254
0
    struct som_misc_symbol_info info;
6255
6256
    /* Derive SOM information from the BFD symbol.  */
6257
0
    som_bfd_derive_misc_symbol_info (curr_bfd, &sym->symbol, &info);
6258
6259
    /* Should we include this symbol?  */
6260
0
    if (info.symbol_type == ST_NULL
6261
0
        || info.symbol_type == ST_SYM_EXT
6262
0
        || info.symbol_type == ST_ARG_EXT)
6263
0
      continue;
6264
6265
    /* Only global symbols and unsatisfied commons.  */
6266
0
    if (info.symbol_scope != SS_UNIVERSAL
6267
0
        && info.symbol_type != ST_STORAGE)
6268
0
      continue;
6269
6270
    /* Do no include undefined symbols.  */
6271
0
    if (bfd_is_und_section (sym->symbol.section))
6272
0
      continue;
6273
6274
    /* Bump the various counters, being careful to honor
6275
       alignment considerations in the string table.  */
6276
0
    (*num_syms)++;
6277
0
    *stringsize += strlen (sym->symbol.name) + 5;
6278
0
    while (*stringsize % 4)
6279
0
      (*stringsize)++;
6280
0
  }
6281
6282
0
      curr_bfd = curr_bfd->archive_next;
6283
0
    }
6284
0
  return true;
6285
0
}
6286
6287
/* Hash a symbol name based on the hashing algorithm presented in the
6288
   SOM ABI.  */
6289
6290
static unsigned int
6291
som_bfd_ar_symbol_hash (asymbol *symbol)
6292
0
{
6293
0
  unsigned int len = strlen (symbol->name);
6294
6295
  /* Names with length 1 are special.  */
6296
0
  if (len == 1)
6297
0
    return 0x1000100 | (symbol->name[0] << 16) | symbol->name[0];
6298
6299
0
  return ((len & 0x7f) << 24) | (symbol->name[1] << 16)
6300
0
    | (symbol->name[len - 2] << 8) | symbol->name[len - 1];
6301
0
}
6302
6303
/* Do the bulk of the work required to write the SOM library
6304
   symbol table.  */
6305
6306
static bool
6307
som_bfd_ar_write_symbol_stuff (bfd *abfd,
6308
             unsigned int nsyms,
6309
             unsigned int string_size,
6310
             struct som_external_lst_header lst,
6311
             unsigned elength)
6312
0
{
6313
0
  char *strings = NULL, *p;
6314
0
  struct som_external_lst_symbol_record *lst_syms = NULL, *curr_lst_sym;
6315
0
  bfd *curr_bfd;
6316
0
  unsigned char *hash_table = NULL;
6317
0
  struct som_external_som_entry *som_dict = NULL;
6318
0
  struct som_external_lst_symbol_record **last_hash_entry = NULL;
6319
0
  unsigned int curr_som_offset, som_index = 0;
6320
0
  size_t amt;
6321
0
  unsigned int module_count;
6322
0
  unsigned int hash_size;
6323
6324
0
  hash_size = bfd_getb32 (lst.hash_size);
6325
0
  if (_bfd_mul_overflow (hash_size, 4, &amt))
6326
0
    {
6327
0
      bfd_set_error (bfd_error_no_memory);
6328
0
      return false;
6329
0
    }
6330
0
  hash_table = bfd_zmalloc (amt);
6331
0
  if (hash_table == NULL && hash_size != 0)
6332
0
    goto error_return;
6333
6334
0
  module_count = bfd_getb32 (lst.module_count);
6335
0
  if (_bfd_mul_overflow (module_count,
6336
0
       sizeof (struct som_external_som_entry), &amt))
6337
0
    {
6338
0
      bfd_set_error (bfd_error_no_memory);
6339
0
      goto error_return;
6340
0
    }
6341
0
  som_dict = bfd_zmalloc (amt);
6342
0
  if (som_dict == NULL && module_count != 0)
6343
0
    goto error_return;
6344
6345
0
  if (_bfd_mul_overflow (hash_size,
6346
0
       sizeof (struct som_external_lst_symbol_record *),
6347
0
       &amt))
6348
0
    {
6349
0
      bfd_set_error (bfd_error_no_memory);
6350
0
      goto error_return;
6351
0
    }
6352
0
  last_hash_entry = bfd_zmalloc (amt);
6353
0
  if (last_hash_entry == NULL && hash_size != 0)
6354
0
    goto error_return;
6355
6356
  /* Symbols have som_index fields, so we have to keep track of the
6357
     index of each SOM in the archive.
6358
6359
     The SOM dictionary has (among other things) the absolute file
6360
     position for the SOM which a particular dictionary entry
6361
     describes.  We have to compute that information as we iterate
6362
     through the SOMs/symbols.  */
6363
0
  som_index = 0;
6364
6365
  /* We add in the size of the archive header twice as the location
6366
     in the SOM dictionary is the actual offset of the SOM, not the
6367
     archive header before the SOM.  */
6368
0
  curr_som_offset = 8 + 2 * sizeof (struct ar_hdr) + bfd_getb32 (lst.file_end);
6369
6370
  /* Make room for the archive header and the contents of the
6371
     extended string table.  Note that elength includes the size
6372
     of the archive header for the extended name table!  */
6373
0
  if (elength)
6374
0
    curr_som_offset += elength;
6375
6376
  /* Make sure we're properly aligned.  */
6377
0
  curr_som_offset = (curr_som_offset + 0x1) & ~0x1;
6378
6379
  /* FIXME should be done with buffers just like everything else...  */
6380
0
  if (_bfd_mul_overflow (nsyms,
6381
0
       sizeof (struct som_external_lst_symbol_record), &amt))
6382
0
    {
6383
0
      bfd_set_error (bfd_error_no_memory);
6384
0
      goto error_return;
6385
0
    }
6386
0
  lst_syms = bfd_malloc (amt);
6387
0
  if (lst_syms == NULL && nsyms != 0)
6388
0
    goto error_return;
6389
0
  strings = bfd_malloc (string_size);
6390
0
  if (strings == NULL && string_size != 0)
6391
0
    goto error_return;
6392
6393
0
  p = strings;
6394
0
  curr_lst_sym = lst_syms;
6395
6396
0
  curr_bfd = abfd->archive_head;
6397
0
  while (curr_bfd != NULL)
6398
0
    {
6399
0
      unsigned int curr_count, i;
6400
0
      som_symbol_type *sym;
6401
6402
      /* Don't bother for non-SOM objects.  */
6403
0
      if (curr_bfd->format != bfd_object
6404
0
    || curr_bfd->xvec->flavour != bfd_target_som_flavour)
6405
0
  {
6406
0
    curr_bfd = curr_bfd->archive_next;
6407
0
    continue;
6408
0
  }
6409
6410
      /* Make sure the symbol table has been read, then snag a pointer
6411
   to it.  It's a little slimey to grab the symbols via obj_som_symtab,
6412
   but doing so avoids allocating lots of extra memory.  */
6413
0
      if (! som_slurp_symbol_table (curr_bfd))
6414
0
  goto error_return;
6415
6416
0
      sym = obj_som_symtab (curr_bfd);
6417
0
      curr_count = bfd_get_symcount (curr_bfd);
6418
6419
0
      for (i = 0; i < curr_count; i++, sym++)
6420
0
  {
6421
0
    struct som_misc_symbol_info info;
6422
0
    struct som_external_lst_symbol_record *last;
6423
0
    unsigned int symbol_pos;
6424
0
    unsigned int slen;
6425
0
    unsigned int symbol_key;
6426
0
    unsigned int flags;
6427
6428
    /* Derive SOM information from the BFD symbol.  */
6429
0
    som_bfd_derive_misc_symbol_info (curr_bfd, &sym->symbol, &info);
6430
6431
    /* Should we include this symbol?  */
6432
0
    if (info.symbol_type == ST_NULL
6433
0
        || info.symbol_type == ST_SYM_EXT
6434
0
        || info.symbol_type == ST_ARG_EXT)
6435
0
      continue;
6436
6437
    /* Only global symbols and unsatisfied commons.  */
6438
0
    if (info.symbol_scope != SS_UNIVERSAL
6439
0
        && info.symbol_type != ST_STORAGE)
6440
0
      continue;
6441
6442
    /* Do no include undefined symbols.  */
6443
0
    if (bfd_is_und_section (sym->symbol.section))
6444
0
      continue;
6445
6446
    /* If this is the first symbol from this SOM, then update
6447
       the SOM dictionary too.  */
6448
0
    if (bfd_getb32 (som_dict[som_index].location) == 0)
6449
0
      {
6450
0
        bfd_putb32 (curr_som_offset, som_dict[som_index].location);
6451
0
        bfd_putb32 (arelt_size (curr_bfd), som_dict[som_index].length);
6452
0
      }
6453
6454
0
    symbol_key = som_bfd_ar_symbol_hash (&sym->symbol);
6455
6456
    /* Fill in the lst symbol record.  */
6457
0
    flags = 0;
6458
0
    if (info.secondary_def)
6459
0
      flags |= LST_SYMBOL_SECONDARY_DEF;
6460
0
    flags |= info.symbol_type << LST_SYMBOL_SYMBOL_TYPE_SH;
6461
0
    flags |= info.symbol_scope << LST_SYMBOL_SYMBOL_SCOPE_SH;
6462
0
    if (bfd_is_com_section (sym->symbol.section))
6463
0
      flags |= LST_SYMBOL_IS_COMMON;
6464
0
    if (info.dup_common)
6465
0
      flags |= LST_SYMBOL_DUP_COMMON;
6466
0
    flags |= 3 << LST_SYMBOL_XLEAST_SH;
6467
0
    flags |= info.arg_reloc << LST_SYMBOL_ARG_RELOC_SH;
6468
0
    bfd_putb32 (flags, curr_lst_sym->flags);
6469
0
    bfd_putb32 (p - strings + 4, curr_lst_sym->name);
6470
0
    bfd_putb32 (0, curr_lst_sym->qualifier_name);
6471
0
    bfd_putb32 (info.symbol_info, curr_lst_sym->symbol_info);
6472
0
    bfd_putb32 (info.symbol_value | info.priv_level,
6473
0
          curr_lst_sym->symbol_value);
6474
0
    bfd_putb32 (0, curr_lst_sym->symbol_descriptor);
6475
0
    curr_lst_sym->reserved = 0;
6476
0
    bfd_putb32 (som_index, curr_lst_sym->som_index);
6477
0
    bfd_putb32 (symbol_key, curr_lst_sym->symbol_key);
6478
0
    bfd_putb32 (0, curr_lst_sym->next_entry);
6479
6480
    /* Insert into the hash table.  */
6481
0
    symbol_pos =
6482
0
      (curr_lst_sym - lst_syms)
6483
0
      * sizeof (struct som_external_lst_symbol_record)
6484
0
      + hash_size * 4
6485
0
      + module_count * sizeof (struct som_external_som_entry)
6486
0
      + sizeof (struct som_external_lst_header);
6487
0
    last = last_hash_entry[symbol_key % hash_size];
6488
0
    if (last != NULL)
6489
0
      {
6490
        /* There is already something at the head of this hash chain,
6491
     so tack this symbol onto the end of the chain.  */
6492
0
        bfd_putb32 (symbol_pos, last->next_entry);
6493
0
      }
6494
0
    else
6495
      /* First entry in this hash chain.  */
6496
0
      bfd_putb32 (symbol_pos, hash_table + 4 * (symbol_key % hash_size));
6497
6498
    /* Keep track of the last symbol we added to this chain so we can
6499
       easily update its next_entry pointer.  */
6500
0
    last_hash_entry[symbol_key % hash_size] = curr_lst_sym;
6501
6502
    /* Update the string table.  */
6503
0
    slen = strlen (sym->symbol.name);
6504
0
    bfd_put_32 (abfd, slen, p);
6505
0
    p += 4;
6506
0
    slen++; /* Nul terminator.  */
6507
0
    memcpy (p, sym->symbol.name, slen);
6508
0
    p += slen;
6509
0
    while (slen % 4)
6510
0
      {
6511
0
        bfd_put_8 (abfd, 0, p);
6512
0
        p++;
6513
0
        slen++;
6514
0
      }
6515
0
    BFD_ASSERT (p <= strings + string_size);
6516
6517
    /* Head to the next symbol.  */
6518
0
    curr_lst_sym++;
6519
0
  }
6520
6521
      /* Keep track of where each SOM will finally reside; then look
6522
   at the next BFD.  */
6523
0
      curr_som_offset += arelt_size (curr_bfd) + sizeof (struct ar_hdr);
6524
6525
      /* A particular object in the archive may have an odd length; the
6526
   linker requires objects begin on an even boundary.  So round
6527
   up the current offset as necessary.  */
6528
0
      curr_som_offset = (curr_som_offset + 0x1) &~ (unsigned) 1;
6529
0
      curr_bfd = curr_bfd->archive_next;
6530
0
      som_index++;
6531
0
    }
6532
6533
  /* Now scribble out the hash table.  */
6534
0
  amt = (size_t) hash_size * 4;
6535
0
  if (bfd_write (hash_table, amt, abfd) != amt)
6536
0
    goto error_return;
6537
6538
  /* Then the SOM dictionary.  */
6539
0
  amt = (size_t) module_count * sizeof (struct som_external_som_entry);
6540
0
  if (bfd_write (som_dict, amt, abfd) != amt)
6541
0
    goto error_return;
6542
6543
  /* The library symbols.  */
6544
0
  amt = (size_t) nsyms * sizeof (struct som_external_lst_symbol_record);
6545
0
  if (bfd_write (lst_syms, amt, abfd) != amt)
6546
0
    goto error_return;
6547
6548
  /* And finally the strings.  */
6549
0
  amt = string_size;
6550
0
  if (bfd_write (strings, amt, abfd) != amt)
6551
0
    goto error_return;
6552
6553
0
  free (hash_table);
6554
0
  free (som_dict);
6555
0
  free (last_hash_entry);
6556
0
  free (lst_syms);
6557
0
  free (strings);
6558
0
  return true;
6559
6560
0
 error_return:
6561
0
  free (hash_table);
6562
0
  free (som_dict);
6563
0
  free (last_hash_entry);
6564
0
  free (lst_syms);
6565
0
  free (strings);
6566
6567
0
  return false;
6568
0
}
6569
6570
/* Write out the LST for the archive.
6571
6572
   You'll never believe this is really how armaps are handled in SOM...  */
6573
6574
static bool
6575
som_write_armap (bfd *abfd,
6576
     unsigned int elength,
6577
     struct orl *map ATTRIBUTE_UNUSED,
6578
     unsigned int orl_count ATTRIBUTE_UNUSED,
6579
     int stridx ATTRIBUTE_UNUSED)
6580
0
{
6581
0
  bfd *curr_bfd;
6582
0
  struct stat statbuf;
6583
0
  unsigned int i, lst_size, nsyms, stringsize;
6584
0
  struct ar_hdr hdr;
6585
0
  struct som_external_lst_header lst;
6586
0
  unsigned char *p;
6587
0
  size_t amt;
6588
0
  unsigned int csum;
6589
0
  unsigned int module_count;
6590
6591
  /* We'll use this for the archive's date and mode later.  */
6592
0
  if (stat (bfd_get_filename (abfd), &statbuf) != 0)
6593
0
    {
6594
0
      bfd_set_error (bfd_error_system_call);
6595
0
      return false;
6596
0
    }
6597
  /* Fudge factor.  */
6598
0
  bfd_ardata (abfd)->armap_timestamp = statbuf.st_mtime + 60;
6599
6600
  /* Account for the lst header first.  */
6601
0
  lst_size = sizeof (struct som_external_lst_header);
6602
6603
  /* Start building the LST header.  */
6604
  /* FIXME:  Do we need to examine each element to determine the
6605
     largest id number?  */
6606
0
  bfd_putb16 (CPU_PA_RISC1_0, &lst.system_id);
6607
0
  bfd_putb16 (LIBMAGIC, &lst.a_magic);
6608
0
  bfd_putb32 (VERSION_ID, &lst.version_id);
6609
0
  bfd_putb32 (0, &lst.file_time.secs);
6610
0
  bfd_putb32 (0, &lst.file_time.nanosecs);
6611
6612
0
  bfd_putb32 (lst_size, &lst.hash_loc);
6613
0
  bfd_putb32 (SOM_LST_HASH_SIZE, &lst.hash_size);
6614
6615
  /* Hash table is a SOM_LST_HASH_SIZE 32bit offsets.  */
6616
0
  lst_size += 4 * SOM_LST_HASH_SIZE;
6617
6618
  /* We need to count the number of SOMs in this archive.  */
6619
0
  curr_bfd = abfd->archive_head;
6620
0
  module_count = 0;
6621
0
  while (curr_bfd != NULL)
6622
0
    {
6623
      /* Only true SOM objects count.  */
6624
0
      if (curr_bfd->format == bfd_object
6625
0
    && curr_bfd->xvec->flavour == bfd_target_som_flavour)
6626
0
  module_count++;
6627
0
      curr_bfd = curr_bfd->archive_next;
6628
0
    }
6629
0
  bfd_putb32 (module_count, &lst.module_count);
6630
0
  bfd_putb32 (module_count, &lst.module_limit);
6631
0
  bfd_putb32 (lst_size, &lst.dir_loc);
6632
0
  lst_size += sizeof (struct som_external_som_entry) * module_count;
6633
6634
  /* We don't support import/export tables, auxiliary headers,
6635
     or free lists yet.  Make the linker work a little harder
6636
     to make our life easier.  */
6637
6638
0
  bfd_putb32 (0, &lst.export_loc);
6639
0
  bfd_putb32 (0, &lst.export_count);
6640
0
  bfd_putb32 (0, &lst.import_loc);
6641
0
  bfd_putb32 (0, &lst.aux_loc);
6642
0
  bfd_putb32 (0, &lst.aux_size);
6643
6644
  /* Count how many symbols we will have on the hash chains and the
6645
     size of the associated string table.  */
6646
0
  if (! som_bfd_prep_for_ar_write (abfd, &nsyms, &stringsize))
6647
0
    return false;
6648
6649
0
  lst_size += sizeof (struct som_external_lst_symbol_record) * nsyms;
6650
6651
  /* For the string table.  One day we might actually use this info
6652
     to avoid small seeks/reads when reading archives.  */
6653
0
  bfd_putb32 (lst_size, &lst.string_loc);
6654
0
  bfd_putb32 (stringsize, &lst.string_size);
6655
0
  lst_size += stringsize;
6656
6657
  /* SOM ABI says this must be zero.  */
6658
0
  bfd_putb32 (0, &lst.free_list);
6659
0
  bfd_putb32 (lst_size, &lst.file_end);
6660
6661
  /* Compute the checksum.  Must happen after the entire lst header
6662
     has filled in.  */
6663
0
  p = (unsigned char *) &lst;
6664
0
  csum = 0;
6665
0
  for (i = 0; i < sizeof (struct som_external_lst_header) - sizeof (int);
6666
0
       i += 4)
6667
0
    csum ^= bfd_getb32 (&p[i]);
6668
0
  bfd_putb32 (csum, &lst.checksum);
6669
6670
0
  sprintf (hdr.ar_name, "/              ");
6671
0
  _bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%-12ld",
6672
0
        bfd_ardata (abfd)->armap_timestamp);
6673
0
  _bfd_ar_spacepad (hdr.ar_uid, sizeof (hdr.ar_uid), "%ld",
6674
0
        statbuf.st_uid);
6675
0
  _bfd_ar_spacepad (hdr.ar_gid, sizeof (hdr.ar_gid), "%ld",
6676
0
        statbuf.st_gid);
6677
0
  _bfd_ar_spacepad (hdr.ar_mode, sizeof (hdr.ar_mode), "%-8o",
6678
0
        (unsigned int)statbuf.st_mode);
6679
0
  _bfd_ar_spacepad (hdr.ar_size, sizeof (hdr.ar_size), "%-10d",
6680
0
        (int) lst_size);
6681
0
  hdr.ar_fmag[0] = '`';
6682
0
  hdr.ar_fmag[1] = '\012';
6683
6684
  /* Turn any nulls into spaces.  */
6685
0
  for (i = 0; i < sizeof (struct ar_hdr); i++)
6686
0
    if (((char *) (&hdr))[i] == '\0')
6687
0
      (((char *) (&hdr))[i]) = ' ';
6688
6689
  /* Scribble out the ar header.  */
6690
0
  amt = sizeof (struct ar_hdr);
6691
0
  if (bfd_write (&hdr, amt, abfd) != amt)
6692
0
    return false;
6693
6694
  /* Now scribble out the lst header.  */
6695
0
  amt = sizeof (struct som_external_lst_header);
6696
0
  if (bfd_write (&lst, amt, abfd) != amt)
6697
0
    return false;
6698
6699
  /* Build and write the armap.  */
6700
0
  if (!som_bfd_ar_write_symbol_stuff (abfd, nsyms, stringsize, lst, elength))
6701
0
    return false;
6702
6703
  /* Done.  */
6704
0
  return true;
6705
0
}
6706
6707
/* Throw away some malloc'd information for this BFD.  */
6708
6709
static bool
6710
som_bfd_free_cached_info (bfd *abfd)
6711
18.1k
{
6712
18.1k
  if (bfd_get_format (abfd) == bfd_object
6713
18.1k
      || bfd_get_format (abfd) == bfd_core)
6714
16.0k
    {
6715
16.0k
      asection *o;
6716
6717
67.9k
#define FREE(x) do { free (x); x = NULL; } while (0)
6718
      /* Free the native string and symbol tables.  */
6719
16.0k
      FREE (obj_som_symtab (abfd));
6720
16.0k
      FREE (obj_som_stringtab (abfd));
6721
51.9k
      for (o = abfd->sections; o != NULL; o = o->next)
6722
35.8k
  {
6723
    /* Free the native relocations.  */
6724
35.8k
    o->reloc_count = (unsigned) -1;
6725
35.8k
    FREE (som_section_data (o)->reloc_stream);
6726
    /* Do not free the generic relocations as they are objalloc'ed.  */
6727
35.8k
  }
6728
16.0k
#undef FREE
6729
16.0k
    }
6730
6731
  /* Do not call _bfd_generic_bfd_free_cached_info here.
6732
     som_write_armap needs to access the bfd objalloc memory.  */
6733
18.1k
  return true;
6734
18.1k
}
6735
6736
/* End of miscellaneous support functions.  */
6737
6738
/* Linker support functions.  */
6739
6740
static bool
6741
som_bfd_link_split_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
6742
0
{
6743
0
  return som_is_subspace (sec) && sec->size > 240000;
6744
0
}
6745
6746
#define som_find_line       _bfd_nosymbols_find_line
6747
#define som_get_symbol_version_string   _bfd_nosymbols_get_symbol_version_string
6748
#define som_close_and_cleanup     _bfd_generic_close_and_cleanup
6749
#define som_read_ar_hdr       _bfd_generic_read_ar_hdr
6750
#define som_write_ar_hdr      _bfd_generic_write_ar_hdr
6751
#define som_openr_next_archived_file    bfd_generic_openr_next_archived_file
6752
#define som_get_elt_at_index      _bfd_generic_get_elt_at_index
6753
#define som_generic_stat_arch_elt   bfd_generic_stat_arch_elt
6754
#define som_truncate_arname     bfd_bsd_truncate_arname
6755
#define som_slurp_extended_name_table   _bfd_slurp_extended_name_table
6756
#define som_construct_extended_name_table _bfd_archive_coff_construct_extended_name_table
6757
#define som_update_armap_timestamp    _bfd_bool_bfd_true
6758
#define som_bfd_is_target_special_symbol        _bfd_bool_bfd_asymbol_false
6759
#define som_get_lineno        _bfd_nosymbols_get_lineno
6760
#define som_bfd_make_debug_symbol   _bfd_nosymbols_bfd_make_debug_symbol
6761
#define som_read_minisymbols      _bfd_generic_read_minisymbols
6762
#define som_minisymbol_to_symbol    _bfd_generic_minisymbol_to_symbol
6763
#define som_bfd_get_relocated_section_contents  bfd_generic_get_relocated_section_contents
6764
#define som_bfd_relax_section     bfd_generic_relax_section
6765
#define som_bfd_link_hash_table_create    _bfd_generic_link_hash_table_create
6766
#define som_bfd_link_add_symbols    _bfd_generic_link_add_symbols
6767
#define som_bfd_link_just_syms      _bfd_generic_link_just_syms
6768
#define som_bfd_copy_link_hash_symbol_type \
6769
  _bfd_generic_copy_link_hash_symbol_type
6770
#define som_bfd_final_link      _bfd_generic_final_link
6771
#define som_bfd_gc_sections     bfd_generic_gc_sections
6772
#define som_bfd_lookup_section_flags    bfd_generic_lookup_section_flags
6773
#define som_bfd_merge_sections      bfd_generic_merge_sections
6774
#define som_bfd_is_group_section    bfd_generic_is_group_section
6775
#define som_bfd_group_name      bfd_generic_group_name
6776
#define som_bfd_discard_group     bfd_generic_discard_group
6777
#define som_section_already_linked    _bfd_generic_section_already_linked
6778
#define som_bfd_define_common_symbol    bfd_generic_define_common_symbol
6779
#define som_bfd_link_hide_symbol    _bfd_generic_link_hide_symbol
6780
#define som_bfd_define_start_stop   bfd_generic_define_start_stop
6781
#define som_bfd_merge_private_bfd_data    _bfd_generic_bfd_merge_private_bfd_data
6782
#define som_init_private_section_data   _bfd_generic_init_private_section_data
6783
#define som_bfd_copy_private_header_data  _bfd_generic_bfd_copy_private_header_data
6784
#define som_bfd_set_private_flags   _bfd_generic_bfd_set_private_flags
6785
#define som_find_inliner_info     _bfd_nosymbols_find_inliner_info
6786
#define som_bfd_link_check_relocs   _bfd_generic_link_check_relocs
6787
#define som_set_reloc       _bfd_generic_set_reloc
6788
6789
const bfd_target hppa_som_vec =
6790
{
6791
  "som",      /* Name.  */
6792
  bfd_target_som_flavour,
6793
  BFD_ENDIAN_BIG,   /* Target byte order.  */
6794
  BFD_ENDIAN_BIG,   /* Target headers byte order.  */
6795
  (HAS_RELOC | EXEC_P |   /* Object flags.  */
6796
   HAS_LINENO | HAS_DEBUG |
6797
   HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED | DYNAMIC),
6798
  (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS | SEC_LINK_ONCE
6799
   | SEC_ALLOC | SEC_LOAD | SEC_RELOC),   /* Section flags.  */
6800
6801
  /* Leading_symbol_char: is the first char of a user symbol
6802
     predictable, and if so what is it.  */
6803
  0,
6804
  '/',        /* AR_pad_char.  */
6805
  14,       /* AR_max_namelen.  */
6806
  0,        /* match priority.  */
6807
  TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols.  */
6808
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
6809
  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
6810
  bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Data.  */
6811
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
6812
  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
6813
  bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Headers.  */
6814
  {_bfd_dummy_target,
6815
   som_object_p,    /* bfd_check_format.  */
6816
   bfd_generic_archive_p,
6817
   _bfd_dummy_target
6818
  },
6819
  {
6820
    _bfd_bool_bfd_false_error,
6821
    som_mkobject,
6822
    _bfd_generic_mkarchive,
6823
    _bfd_bool_bfd_false_error
6824
  },
6825
  {
6826
    _bfd_bool_bfd_false_error,
6827
    som_write_object_contents,
6828
    _bfd_write_archive_contents,
6829
    _bfd_bool_bfd_false_error,
6830
  },
6831
#undef som
6832
6833
  BFD_JUMP_TABLE_GENERIC (som),
6834
  BFD_JUMP_TABLE_COPY (som),
6835
  BFD_JUMP_TABLE_CORE (_bfd_nocore),
6836
  BFD_JUMP_TABLE_ARCHIVE (som),
6837
  BFD_JUMP_TABLE_SYMBOLS (som),
6838
  BFD_JUMP_TABLE_RELOCS (som),
6839
  BFD_JUMP_TABLE_WRITE (som),
6840
  BFD_JUMP_TABLE_LINK (som),
6841
  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
6842
6843
  NULL,
6844
6845
  NULL
6846
};
6847