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