2005-05-04 Paolo Bonzini <bonzini@gnu.org>
[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,
9553c638 3 2000, 2001, 2002, 2003, 2004, 2005
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
23 Foundation, Inc., 59 Temple Place - Suite 330, 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
NC
1056try_prev_fixup (bfd *abfd ATTRIBUTE_UNUSED,
1057 int *subspace_reloc_sizep,
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
JL
2960 size_t tmp_space_size = SOM_TMP_BUFSIZE;
2961 unsigned char *tmp_space = alloca (tmp_space_size);
2962 unsigned 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
JL
3065 size_t tmp_space_size = SOM_TMP_BUFSIZE;
3066 unsigned char *tmp_space = alloca (tmp_space_size);
3067 unsigned char *p = tmp_space;
3068
252b5132
RH
3069 unsigned int strings_size = 0;
3070 unsigned 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;
3230 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);
3579 int i, num_syms, strings_size;
3580 int subspace_index = 0;
3581 file_ptr location;
3582 asection *section;
3583 unsigned long current_offset;
3584 unsigned int 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
RH
4844{
4845 char *external_relocs;
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{
dc810e39 4962 bfd_size_type amt = sizeof (struct som_section_data_struct);
116c20d2
NC
4963
4964 newsect->used_by_bfd = bfd_zalloc (abfd, amt);
252b5132 4965 if (!newsect->used_by_bfd)
b34976b6 4966 return FALSE;
252b5132
RH
4967 newsect->alignment_power = 3;
4968
7eae7d22 4969 /* We allow more than three sections internally. */
b34976b6 4970 return TRUE;
252b5132
RH
4971}
4972
4973/* Copy any private info we understand from the input symbol
4974 to the output symbol. */
4975
b34976b6 4976static bfd_boolean
116c20d2
NC
4977som_bfd_copy_private_symbol_data (bfd *ibfd,
4978 asymbol *isymbol,
4979 bfd *obfd,
4980 asymbol *osymbol)
252b5132
RH
4981{
4982 struct som_symbol *input_symbol = (struct som_symbol *) isymbol;
4983 struct som_symbol *output_symbol = (struct som_symbol *) osymbol;
4984
4985 /* One day we may try to grok other private data. */
4986 if (ibfd->xvec->flavour != bfd_target_som_flavour
4987 || obfd->xvec->flavour != bfd_target_som_flavour)
b34976b6 4988 return FALSE;
252b5132
RH
4989
4990 /* The only private information we need to copy is the argument relocation
4991 bits. */
4992 output_symbol->tc_data.ap.hppa_arg_reloc =
4993 input_symbol->tc_data.ap.hppa_arg_reloc;
4994
b34976b6 4995 return TRUE;
252b5132
RH
4996}
4997
4998/* Copy any private info we understand from the input section
4999 to the output section. */
7eae7d22 5000
b34976b6 5001static bfd_boolean
116c20d2
NC
5002som_bfd_copy_private_section_data (bfd *ibfd,
5003 asection *isection,
5004 bfd *obfd,
5005 asection *osection)
252b5132 5006{
dc810e39
AM
5007 bfd_size_type amt;
5008
252b5132
RH
5009 /* One day we may try to grok other private data. */
5010 if (ibfd->xvec->flavour != bfd_target_som_flavour
5011 || obfd->xvec->flavour != bfd_target_som_flavour
5012 || (!som_is_space (isection) && !som_is_subspace (isection)))
b34976b6 5013 return TRUE;
252b5132 5014
dc810e39 5015 amt = sizeof (struct som_copyable_section_data_struct);
116c20d2 5016 som_section_data (osection)->copy_data = bfd_zalloc (obfd, amt);
252b5132 5017 if (som_section_data (osection)->copy_data == NULL)
b34976b6 5018 return FALSE;
252b5132
RH
5019
5020 memcpy (som_section_data (osection)->copy_data,
5021 som_section_data (isection)->copy_data,
5022 sizeof (struct som_copyable_section_data_struct));
5023
5024 /* Reparent if necessary. */
5025 if (som_section_data (osection)->copy_data->container)
5026 som_section_data (osection)->copy_data->container =
5027 som_section_data (osection)->copy_data->container->output_section;
5028
b34976b6 5029 return TRUE;
252b5132
RH
5030}
5031
5032/* Copy any private info we understand from the input bfd
5033 to the output bfd. */
5034
b34976b6 5035static bfd_boolean
116c20d2 5036som_bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
252b5132
RH
5037{
5038 /* One day we may try to grok other private data. */
5039 if (ibfd->xvec->flavour != bfd_target_som_flavour
5040 || obfd->xvec->flavour != bfd_target_som_flavour)
b34976b6 5041 return TRUE;
252b5132
RH
5042
5043 /* Allocate some memory to hold the data we need. */
116c20d2 5044 obj_som_exec_data (obfd) = bfd_zalloc (obfd, (bfd_size_type) sizeof (struct som_exec_data));
252b5132 5045 if (obj_som_exec_data (obfd) == NULL)
b34976b6 5046 return FALSE;
252b5132
RH
5047
5048 /* Now copy the data. */
5049 memcpy (obj_som_exec_data (obfd), obj_som_exec_data (ibfd),
5050 sizeof (struct som_exec_data));
5051
b34976b6 5052 return TRUE;
252b5132
RH
5053}
5054
e6dc21b6
MM
5055/* Display the SOM header. */
5056
5057static bfd_boolean
5058som_bfd_print_private_bfd_data (bfd *abfd, void *farg)
5059{
5060 struct som_exec_auxhdr *exec_header;
5061 struct aux_id* auxhdr;
5062 FILE *f;
5063
5064 f = (FILE *) farg;
5065
5066 exec_header = obj_som_exec_hdr (abfd);
5067 if (exec_header)
5068 {
5069 fprintf (f, _("\nExec Auxiliary Header\n"));
5070 fprintf (f, " flags ");
5071 auxhdr = &exec_header->som_auxhdr;
5072 if (auxhdr->mandatory)
5073 fprintf (f, "mandatory ");
5074 if (auxhdr->copy)
5075 fprintf (f, "copy ");
5076 if (auxhdr->append)
5077 fprintf (f, "append ");
5078 if (auxhdr->ignore)
5079 fprintf (f, "ignore ");
5080 fprintf (f, "\n");
5081 fprintf (f, " type %#x\n", auxhdr->type);
5082 fprintf (f, " length %#x\n", auxhdr->length);
0858d3ec
JG
5083
5084 /* Note that, depending on the HP-UX version, the following fields can be
5085 either ints, or longs. */
5086
5087 fprintf (f, " text size %#lx\n", (long) exec_header->exec_tsize);
5088 fprintf (f, " text memory offset %#lx\n", (long) exec_header->exec_tmem);
5089 fprintf (f, " text file offset %#lx\n", (long) exec_header->exec_tfile);
5090 fprintf (f, " data size %#lx\n", (long) exec_header->exec_dsize);
5091 fprintf (f, " data memory offset %#lx\n", (long) exec_header->exec_dmem);
5092 fprintf (f, " data file offset %#lx\n", (long) exec_header->exec_dfile);
5093 fprintf (f, " bss size %#lx\n", (long) exec_header->exec_bsize);
5094 fprintf (f, " entry point %#lx\n", (long) exec_header->exec_entry);
5095 fprintf (f, " loader flags %#lx\n", (long) exec_header->exec_flags);
5096 fprintf (f, " bss initializer %#lx\n", (long) exec_header->exec_bfill);
e6dc21b6
MM
5097 }
5098
5099 return TRUE;
5100}
5101
252b5132
RH
5102/* Set backend info for sections which can not be described
5103 in the BFD data structures. */
5104
b34976b6 5105bfd_boolean
116c20d2
NC
5106bfd_som_set_section_attributes (asection *section,
5107 int defined,
5108 int private,
5109 unsigned int sort_key,
5110 int spnum)
252b5132
RH
5111{
5112 /* Allocate memory to hold the magic information. */
5113 if (som_section_data (section)->copy_data == NULL)
5114 {
dc810e39 5115 bfd_size_type amt = sizeof (struct som_copyable_section_data_struct);
116c20d2
NC
5116
5117 som_section_data (section)->copy_data = bfd_zalloc (section->owner, amt);
252b5132 5118 if (som_section_data (section)->copy_data == NULL)
b34976b6 5119 return FALSE;
252b5132
RH
5120 }
5121 som_section_data (section)->copy_data->sort_key = sort_key;
5122 som_section_data (section)->copy_data->is_defined = defined;
5123 som_section_data (section)->copy_data->is_private = private;
5124 som_section_data (section)->copy_data->container = section;
5125 som_section_data (section)->copy_data->space_number = spnum;
b34976b6 5126 return TRUE;
252b5132
RH
5127}
5128
6fa957a9 5129/* Set backend info for subsections which can not be described
252b5132
RH
5130 in the BFD data structures. */
5131
b34976b6 5132bfd_boolean
116c20d2
NC
5133bfd_som_set_subsection_attributes (asection *section,
5134 asection *container,
5135 int access,
5136 unsigned int sort_key,
5137 int quadrant,
5138 int comdat,
5139 int common,
5140 int dup_common)
252b5132
RH
5141{
5142 /* Allocate memory to hold the magic information. */
5143 if (som_section_data (section)->copy_data == NULL)
5144 {
dc810e39 5145 bfd_size_type amt = sizeof (struct som_copyable_section_data_struct);
116c20d2
NC
5146
5147 som_section_data (section)->copy_data = bfd_zalloc (section->owner, amt);
252b5132 5148 if (som_section_data (section)->copy_data == NULL)
b34976b6 5149 return FALSE;
252b5132
RH
5150 }
5151 som_section_data (section)->copy_data->sort_key = sort_key;
5152 som_section_data (section)->copy_data->access_control_bits = access;
5153 som_section_data (section)->copy_data->quadrant = quadrant;
5154 som_section_data (section)->copy_data->container = container;
351e2b5a
DA
5155 som_section_data (section)->copy_data->is_comdat = comdat;
5156 som_section_data (section)->copy_data->is_common = common;
5157 som_section_data (section)->copy_data->dup_common = dup_common;
b34976b6 5158 return TRUE;
252b5132
RH
5159}
5160
5161/* Set the full SOM symbol type. SOM needs far more symbol information
5162 than any other object file format I'm aware of. It is mandatory
5163 to be able to know if a symbol is an entry point, millicode, data,
5164 code, absolute, storage request, or procedure label. If you get
5165 the symbol type wrong your program will not link. */
5166
5167void
116c20d2 5168bfd_som_set_symbol_type (asymbol *symbol, unsigned int type)
252b5132
RH
5169{
5170 som_symbol_data (symbol)->som_type = type;
5171}
5172
5173/* Attach an auxiliary header to the BFD backend so that it may be
5174 written into the object file. */
7eae7d22 5175
b34976b6 5176bfd_boolean
116c20d2 5177bfd_som_attach_aux_hdr (bfd *abfd, int type, char *string)
252b5132 5178{
dc810e39
AM
5179 bfd_size_type amt;
5180
252b5132
RH
5181 if (type == VERSION_AUX_ID)
5182 {
dc810e39 5183 size_t len = strlen (string);
252b5132
RH
5184 int pad = 0;
5185
5186 if (len % 4)
5187 pad = (4 - (len % 4));
dc810e39 5188 amt = sizeof (struct aux_id) + sizeof (unsigned int) + len + pad;
116c20d2 5189 obj_som_version_hdr (abfd) = bfd_zalloc (abfd, amt);
252b5132 5190 if (!obj_som_version_hdr (abfd))
b34976b6 5191 return FALSE;
252b5132
RH
5192 obj_som_version_hdr (abfd)->header_id.type = VERSION_AUX_ID;
5193 obj_som_version_hdr (abfd)->header_id.length = len + pad;
5194 obj_som_version_hdr (abfd)->header_id.length += sizeof (int);
5195 obj_som_version_hdr (abfd)->string_length = len;
5196 strncpy (obj_som_version_hdr (abfd)->user_string, string, len);
5197 }
5198 else if (type == COPYRIGHT_AUX_ID)
5199 {
5200 int len = strlen (string);
5201 int pad = 0;
5202
5203 if (len % 4)
5204 pad = (4 - (len % 4));
dc810e39 5205 amt = sizeof (struct aux_id) + sizeof (unsigned int) + len + pad;
116c20d2 5206 obj_som_copyright_hdr (abfd) = bfd_zalloc (abfd, amt);
252b5132 5207 if (!obj_som_copyright_hdr (abfd))
b34976b6 5208 return FALSE;
252b5132
RH
5209 obj_som_copyright_hdr (abfd)->header_id.type = COPYRIGHT_AUX_ID;
5210 obj_som_copyright_hdr (abfd)->header_id.length = len + pad;
5211 obj_som_copyright_hdr (abfd)->header_id.length += sizeof (int);
5212 obj_som_copyright_hdr (abfd)->string_length = len;
5213 strcpy (obj_som_copyright_hdr (abfd)->copyright, string);
5214 }
b34976b6 5215 return TRUE;
252b5132
RH
5216}
5217
19852a2a 5218/* Attach a compilation unit header to the BFD backend so that it may be
252b5132
RH
5219 written into the object file. */
5220
b34976b6 5221bfd_boolean
116c20d2
NC
5222bfd_som_attach_compilation_unit (bfd *abfd,
5223 const char *name,
5224 const char *language_name,
5225 const char *product_id,
5226 const char *version_id)
252b5132 5227{
dc810e39 5228 COMPUNIT *n = (COMPUNIT *) bfd_zalloc (abfd, (bfd_size_type) COMPUNITSZ);
116c20d2 5229
252b5132 5230 if (n == NULL)
b34976b6 5231 return FALSE;
252b5132
RH
5232
5233#define STRDUP(f) \
5234 if (f != NULL) \
5235 { \
dc810e39 5236 n->f.n_name = bfd_alloc (abfd, (bfd_size_type) strlen (f) + 1); \
252b5132 5237 if (n->f.n_name == NULL) \
b34976b6 5238 return FALSE; \
252b5132
RH
5239 strcpy (n->f.n_name, f); \
5240 }
5241
5242 STRDUP (name);
5243 STRDUP (language_name);
5244 STRDUP (product_id);
5245 STRDUP (version_id);
5246
5247#undef STRDUP
5248
5249 obj_som_compilation_unit (abfd) = n;
5250
b34976b6 5251 return TRUE;
252b5132
RH
5252}
5253
b34976b6 5254static bfd_boolean
116c20d2
NC
5255som_get_section_contents (bfd *abfd,
5256 sec_ptr section,
6a808a40 5257 void *location,
116c20d2
NC
5258 file_ptr offset,
5259 bfd_size_type count)
252b5132
RH
5260{
5261 if (count == 0 || ((section->flags & SEC_HAS_CONTENTS) == 0))
b34976b6 5262 return TRUE;
eea6121a 5263 if ((bfd_size_type) (offset+count) > section->size
dc810e39
AM
5264 || bfd_seek (abfd, (file_ptr) (section->filepos + offset), SEEK_SET) != 0
5265 || bfd_bread (location, count, abfd) != count)
34f304a7 5266 return FALSE; /* On error. */
b34976b6 5267 return TRUE;
252b5132
RH
5268}
5269
b34976b6 5270static bfd_boolean
116c20d2
NC
5271som_set_section_contents (bfd *abfd,
5272 sec_ptr section,
6a808a40 5273 const void *location,
116c20d2
NC
5274 file_ptr offset,
5275 bfd_size_type count)
252b5132 5276{
82e51918 5277 if (! abfd->output_has_begun)
252b5132
RH
5278 {
5279 /* Set up fixed parts of the file, space, and subspace headers.
5280 Notify the world that output has begun. */
5281 som_prep_headers (abfd);
b34976b6 5282 abfd->output_has_begun = TRUE;
252b5132
RH
5283 /* Start writing the object file. This include all the string
5284 tables, fixup streams, and other portions of the object file. */
5285 som_begin_writing (abfd);
5286 }
5287
5288 /* Only write subspaces which have "real" contents (eg. the contents
5289 are not generated at run time by the OS). */
5290 if (!som_is_subspace (section)
5291 || ((section->flags & SEC_HAS_CONTENTS) == 0))
b34976b6 5292 return TRUE;
252b5132
RH
5293
5294 /* Seek to the proper offset within the object file and write the
5295 data. */
6fa957a9 5296 offset += som_section_data (section)->subspace_dict->file_loc_init_value;
dc810e39 5297 if (bfd_seek (abfd, offset, SEEK_SET) != 0)
b34976b6 5298 return FALSE;
252b5132 5299
5198ba8b 5300 if (bfd_bwrite (location, count, abfd) != count)
b34976b6
AM
5301 return FALSE;
5302 return TRUE;
252b5132
RH
5303}
5304
b34976b6 5305static bfd_boolean
116c20d2
NC
5306som_set_arch_mach (bfd *abfd,
5307 enum bfd_architecture arch,
5308 unsigned long machine)
252b5132 5309{
7eae7d22 5310 /* Allow any architecture to be supported by the SOM backend. */
252b5132
RH
5311 return bfd_default_set_arch_mach (abfd, arch, machine);
5312}
5313
b34976b6 5314static bfd_boolean
116c20d2
NC
5315som_find_nearest_line (bfd *abfd ATTRIBUTE_UNUSED,
5316 asection *section ATTRIBUTE_UNUSED,
5317 asymbol **symbols ATTRIBUTE_UNUSED,
5318 bfd_vma offset ATTRIBUTE_UNUSED,
5319 const char **filename_ptr ATTRIBUTE_UNUSED,
5320 const char **functionname_ptr ATTRIBUTE_UNUSED,
5321 unsigned int *line_ptr ATTRIBUTE_UNUSED)
252b5132 5322{
b34976b6 5323 return FALSE;
252b5132
RH
5324}
5325
5326static int
116c20d2
NC
5327som_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
5328 bfd_boolean reloc ATTRIBUTE_UNUSED)
252b5132
RH
5329{
5330 (*_bfd_error_handler) (_("som_sizeof_headers unimplemented"));
5331 fflush (stderr);
5332 abort ();
b34976b6 5333 return 0;
252b5132
RH
5334}
5335
5336/* Return the single-character symbol type corresponding to
5337 SOM section S, or '?' for an unknown SOM section. */
5338
5339static char
116c20d2 5340som_section_type (const char *s)
252b5132
RH
5341{
5342 const struct section_to_type *t;
5343
5344 for (t = &stt[0]; t->section; t++)
5345 if (!strcmp (s, t->section))
5346 return t->type;
5347 return '?';
5348}
5349
5350static int
116c20d2 5351som_decode_symclass (asymbol *symbol)
252b5132
RH
5352{
5353 char c;
5354
5355 if (bfd_is_com_section (symbol->section))
5356 return 'C';
5357 if (bfd_is_und_section (symbol->section))
5358 return 'U';
5359 if (bfd_is_ind_section (symbol->section))
5360 return 'I';
10febd84
CM
5361 if (symbol->flags & BSF_WEAK)
5362 return 'W';
7eae7d22 5363 if (!(symbol->flags & (BSF_GLOBAL | BSF_LOCAL)))
252b5132
RH
5364 return '?';
5365
5366 if (bfd_is_abs_section (symbol->section)
5367 || (som_symbol_data (symbol) != NULL
5368 && som_symbol_data (symbol)->som_type == SYMBOL_TYPE_ABSOLUTE))
5369 c = 'a';
5370 else if (symbol->section)
5371 c = som_section_type (symbol->section->name);
5372 else
5373 return '?';
5374 if (symbol->flags & BSF_GLOBAL)
3882b010 5375 c = TOUPPER (c);
252b5132
RH
5376 return c;
5377}
5378
5379/* Return information about SOM symbol SYMBOL in RET. */
5380
5381static void
116c20d2
NC
5382som_get_symbol_info (bfd *ignore_abfd ATTRIBUTE_UNUSED,
5383 asymbol *symbol,
5384 symbol_info *ret)
252b5132
RH
5385{
5386 ret->type = som_decode_symclass (symbol);
5387 if (ret->type != 'U')
7eae7d22 5388 ret->value = symbol->value + symbol->section->vma;
252b5132
RH
5389 else
5390 ret->value = 0;
5391 ret->name = symbol->name;
5392}
5393
5394/* Count the number of symbols in the archive symbol table. Necessary
5395 so that we can allocate space for all the carsyms at once. */
5396
b34976b6 5397static bfd_boolean
116c20d2
NC
5398som_bfd_count_ar_symbols (bfd *abfd,
5399 struct lst_header *lst_header,
5400 symindex *count)
252b5132
RH
5401{
5402 unsigned int i;
5403 unsigned int *hash_table = NULL;
dc810e39 5404 bfd_size_type amt;
252b5132
RH
5405 file_ptr lst_filepos = bfd_tell (abfd) - sizeof (struct lst_header);
5406
dc810e39
AM
5407 amt = lst_header->hash_size;
5408 amt *= sizeof (unsigned int);
116c20d2 5409 hash_table = bfd_malloc (amt);
252b5132
RH
5410 if (hash_table == NULL && lst_header->hash_size != 0)
5411 goto error_return;
5412
5413 /* Don't forget to initialize the counter! */
5414 *count = 0;
5415
5416 /* Read in the hash table. The has table is an array of 32bit file offsets
5417 which point to the hash chains. */
116c20d2 5418 if (bfd_bread ((void *) hash_table, amt, abfd) != amt)
252b5132
RH
5419 goto error_return;
5420
5421 /* Walk each chain counting the number of symbols found on that particular
5422 chain. */
5423 for (i = 0; i < lst_header->hash_size; i++)
5424 {
5425 struct lst_symbol_record lst_symbol;
5426
5427 /* An empty chain has zero as it's file offset. */
5428 if (hash_table[i] == 0)
5429 continue;
5430
5431 /* Seek to the first symbol in this hash chain. */
dc810e39 5432 if (bfd_seek (abfd, lst_filepos + hash_table[i], SEEK_SET) != 0)
252b5132
RH
5433 goto error_return;
5434
5435 /* Read in this symbol and update the counter. */
dc810e39 5436 amt = sizeof (lst_symbol);
116c20d2 5437 if (bfd_bread ((void *) &lst_symbol, amt, abfd) != amt)
252b5132
RH
5438 goto error_return;
5439
5440 (*count)++;
5441
5442 /* Now iterate through the rest of the symbols on this chain. */
5443 while (lst_symbol.next_entry)
5444 {
5445
5446 /* Seek to the next symbol. */
5447 if (bfd_seek (abfd, lst_filepos + lst_symbol.next_entry, SEEK_SET)
dc810e39 5448 != 0)
252b5132
RH
5449 goto error_return;
5450
5451 /* Read the symbol in and update the counter. */
dc810e39 5452 amt = sizeof (lst_symbol);
116c20d2 5453 if (bfd_bread ((void *) &lst_symbol, amt, abfd) != amt)
252b5132
RH
5454 goto error_return;
5455
5456 (*count)++;
5457 }
5458 }
5459 if (hash_table != NULL)
5460 free (hash_table);
b34976b6 5461 return TRUE;
252b5132
RH
5462
5463 error_return:
5464 if (hash_table != NULL)
5465 free (hash_table);
b34976b6 5466 return FALSE;
252b5132
RH
5467}
5468
5469/* Fill in the canonical archive symbols (SYMS) from the archive described
5470 by ABFD and LST_HEADER. */
5471
b34976b6 5472static bfd_boolean
116c20d2
NC
5473som_bfd_fill_in_ar_symbols (bfd *abfd,
5474 struct lst_header *lst_header,
5475 carsym **syms)
252b5132
RH
5476{
5477 unsigned int i, len;
5478 carsym *set = syms[0];
5479 unsigned int *hash_table = NULL;
5480 struct som_entry *som_dict = NULL;
dc810e39 5481 bfd_size_type amt;
252b5132
RH
5482 file_ptr lst_filepos = bfd_tell (abfd) - sizeof (struct lst_header);
5483
dc810e39
AM
5484 amt = lst_header->hash_size;
5485 amt *= sizeof (unsigned int);
116c20d2 5486 hash_table = bfd_malloc (amt);
252b5132
RH
5487 if (hash_table == NULL && lst_header->hash_size != 0)
5488 goto error_return;
5489
252b5132
RH
5490 /* Read in the hash table. The has table is an array of 32bit file offsets
5491 which point to the hash chains. */
116c20d2 5492 if (bfd_bread ((void *) hash_table, amt, abfd) != amt)
252b5132
RH
5493 goto error_return;
5494
5495 /* Seek to and read in the SOM dictionary. We will need this to fill
5496 in the carsym's filepos field. */
dc810e39
AM
5497 if (bfd_seek (abfd, lst_filepos + lst_header->dir_loc, SEEK_SET) != 0)
5498 goto error_return;
5499
5500 amt = lst_header->module_count;
5501 amt *= sizeof (struct som_entry);
116c20d2 5502 som_dict = bfd_malloc (amt);
dc810e39 5503 if (som_dict == NULL && lst_header->module_count != 0)
252b5132
RH
5504 goto error_return;
5505
116c20d2 5506 if (bfd_bread ((void *) som_dict, amt, abfd) != amt)
252b5132
RH
5507 goto error_return;
5508
5509 /* Walk each chain filling in the carsyms as we go along. */
5510 for (i = 0; i < lst_header->hash_size; i++)
5511 {
5512 struct lst_symbol_record lst_symbol;
5513
5514 /* An empty chain has zero as it's file offset. */
5515 if (hash_table[i] == 0)
5516 continue;
5517
5518 /* Seek to and read the first symbol on the chain. */
dc810e39 5519 if (bfd_seek (abfd, lst_filepos + hash_table[i], SEEK_SET) != 0)
252b5132
RH
5520 goto error_return;
5521
dc810e39 5522 amt = sizeof (lst_symbol);
116c20d2 5523 if (bfd_bread ((void *) &lst_symbol, amt, abfd) != amt)
252b5132
RH
5524 goto error_return;
5525
5526 /* Get the name of the symbol, first get the length which is stored
5527 as a 32bit integer just before the symbol.
5528
5529 One might ask why we don't just read in the entire string table
5530 and index into it. Well, according to the SOM ABI the string
5531 index can point *anywhere* in the archive to save space, so just
5532 using the string table would not be safe. */
5533 if (bfd_seek (abfd, lst_filepos + lst_header->string_loc
dc810e39 5534 + lst_symbol.name.n_strx - 4, SEEK_SET) != 0)
252b5132
RH
5535 goto error_return;
5536
dc810e39 5537 if (bfd_bread (&len, (bfd_size_type) 4, abfd) != 4)
252b5132
RH
5538 goto error_return;
5539
5540 /* Allocate space for the name and null terminate it too. */
dc810e39 5541 set->name = bfd_zalloc (abfd, (bfd_size_type) len + 1);
252b5132
RH
5542 if (!set->name)
5543 goto error_return;
dc810e39 5544 if (bfd_bread (set->name, (bfd_size_type) len, abfd) != len)
252b5132
RH
5545 goto error_return;
5546
5547 set->name[len] = 0;
5548
5549 /* Fill in the file offset. Note that the "location" field points
5550 to the SOM itself, not the ar_hdr in front of it. */
5551 set->file_offset = som_dict[lst_symbol.som_index].location
5552 - sizeof (struct ar_hdr);
5553
5554 /* Go to the next symbol. */
5555 set++;
5556
5557 /* Iterate through the rest of the chain. */
5558 while (lst_symbol.next_entry)
5559 {
5560 /* Seek to the next symbol and read it in. */
dc810e39
AM
5561 if (bfd_seek (abfd, lst_filepos + lst_symbol.next_entry, SEEK_SET)
5562 != 0)
252b5132
RH
5563 goto error_return;
5564
dc810e39 5565 amt = sizeof (lst_symbol);
116c20d2 5566 if (bfd_bread ((void *) &lst_symbol, amt, abfd) != amt)
252b5132
RH
5567 goto error_return;
5568
5569 /* Seek to the name length & string and read them in. */
6fa957a9 5570 if (bfd_seek (abfd, lst_filepos + lst_header->string_loc
dc810e39 5571 + lst_symbol.name.n_strx - 4, SEEK_SET) != 0)
252b5132
RH
5572 goto error_return;
5573
dc810e39 5574 if (bfd_bread (&len, (bfd_size_type) 4, abfd) != 4)
252b5132
RH
5575 goto error_return;
5576
5577 /* Allocate space for the name and null terminate it too. */
dc810e39 5578 set->name = bfd_zalloc (abfd, (bfd_size_type) len + 1);
252b5132
RH
5579 if (!set->name)
5580 goto error_return;
5581
dc810e39 5582 if (bfd_bread (set->name, (bfd_size_type) len, abfd) != len)
252b5132
RH
5583 goto error_return;
5584 set->name[len] = 0;
5585
5586 /* Fill in the file offset. Note that the "location" field points
5587 to the SOM itself, not the ar_hdr in front of it. */
5588 set->file_offset = som_dict[lst_symbol.som_index].location
5589 - sizeof (struct ar_hdr);
5590
5591 /* Go on to the next symbol. */
5592 set++;
5593 }
5594 }
6fa957a9 5595 /* If we haven't died by now, then we successfully read the entire
252b5132
RH
5596 archive symbol table. */
5597 if (hash_table != NULL)
5598 free (hash_table);
5599 if (som_dict != NULL)
5600 free (som_dict);
b34976b6 5601 return TRUE;
252b5132
RH
5602
5603 error_return:
5604 if (hash_table != NULL)
5605 free (hash_table);
5606 if (som_dict != NULL)
5607 free (som_dict);
b34976b6 5608 return FALSE;
252b5132
RH
5609}
5610
5611/* Read in the LST from the archive. */
7eae7d22 5612
b34976b6 5613static bfd_boolean
116c20d2 5614som_slurp_armap (bfd *abfd)
252b5132
RH
5615{
5616 struct lst_header lst_header;
5617 struct ar_hdr ar_header;
5618 unsigned int parsed_size;
5619 struct artdata *ardata = bfd_ardata (abfd);
5620 char nextname[17];
dc810e39 5621 bfd_size_type amt = 16;
116c20d2 5622 int i = bfd_bread ((void *) nextname, amt, abfd);
252b5132
RH
5623
5624 /* Special cases. */
5625 if (i == 0)
b34976b6 5626 return TRUE;
252b5132 5627 if (i != 16)
b34976b6 5628 return FALSE;
252b5132 5629
dc810e39 5630 if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
b34976b6 5631 return FALSE;
252b5132
RH
5632
5633 /* For archives without .o files there is no symbol table. */
5634 if (strncmp (nextname, "/ ", 16))
5635 {
b34976b6
AM
5636 bfd_has_map (abfd) = FALSE;
5637 return TRUE;
252b5132
RH
5638 }
5639
5640 /* Read in and sanity check the archive header. */
dc810e39 5641 amt = sizeof (struct ar_hdr);
116c20d2 5642 if (bfd_bread ((void *) &ar_header, amt, abfd) != amt)
b34976b6 5643 return FALSE;
252b5132
RH
5644
5645 if (strncmp (ar_header.ar_fmag, ARFMAG, 2))
5646 {
5647 bfd_set_error (bfd_error_malformed_archive);
b34976b6 5648 return FALSE;
252b5132
RH
5649 }
5650
5651 /* How big is the archive symbol table entry? */
5652 errno = 0;
5653 parsed_size = strtol (ar_header.ar_size, NULL, 10);
5654 if (errno != 0)
5655 {
5656 bfd_set_error (bfd_error_malformed_archive);
b34976b6 5657 return FALSE;
252b5132
RH
5658 }
5659
5660 /* Save off the file offset of the first real user data. */
5661 ardata->first_file_filepos = bfd_tell (abfd) + parsed_size;
5662
5663 /* Read in the library symbol table. We'll make heavy use of this
5664 in just a minute. */
dc810e39 5665 amt = sizeof (struct lst_header);
116c20d2 5666 if (bfd_bread ((void *) &lst_header, amt, abfd) != amt)
b34976b6 5667 return FALSE;
252b5132
RH
5668
5669 /* Sanity check. */
5670 if (lst_header.a_magic != LIBMAGIC)
5671 {
5672 bfd_set_error (bfd_error_malformed_archive);
b34976b6 5673 return FALSE;
252b5132
RH
5674 }
5675
5676 /* Count the number of symbols in the library symbol table. */
82e51918 5677 if (! som_bfd_count_ar_symbols (abfd, &lst_header, &ardata->symdef_count))
b34976b6 5678 return FALSE;
252b5132
RH
5679
5680 /* Get back to the start of the library symbol table. */
dc810e39
AM
5681 if (bfd_seek (abfd, (ardata->first_file_filepos - parsed_size
5682 + sizeof (struct lst_header)), SEEK_SET) != 0)
b34976b6 5683 return FALSE;
252b5132 5684
7dee875e 5685 /* Initialize the cache and allocate space for the library symbols. */
252b5132 5686 ardata->cache = 0;
dc810e39
AM
5687 amt = ardata->symdef_count;
5688 amt *= sizeof (carsym);
116c20d2 5689 ardata->symdefs = bfd_alloc (abfd, amt);
252b5132 5690 if (!ardata->symdefs)
b34976b6 5691 return FALSE;
252b5132
RH
5692
5693 /* Now fill in the canonical archive symbols. */
82e51918 5694 if (! som_bfd_fill_in_ar_symbols (abfd, &lst_header, &ardata->symdefs))
b34976b6 5695 return FALSE;
252b5132
RH
5696
5697 /* Seek back to the "first" file in the archive. Note the "first"
5698 file may be the extended name table. */
dc810e39 5699 if (bfd_seek (abfd, ardata->first_file_filepos, SEEK_SET) != 0)
b34976b6 5700 return FALSE;
252b5132
RH
5701
5702 /* Notify the generic archive code that we have a symbol map. */
b34976b6
AM
5703 bfd_has_map (abfd) = TRUE;
5704 return TRUE;
252b5132
RH
5705}
5706
5707/* Begin preparing to write a SOM library symbol table.
5708
5709 As part of the prep work we need to determine the number of symbols
5710 and the size of the associated string section. */
5711
b34976b6 5712static bfd_boolean
116c20d2
NC
5713som_bfd_prep_for_ar_write (bfd *abfd,
5714 unsigned int *num_syms,
5715 unsigned int *stringsize)
252b5132
RH
5716{
5717 bfd *curr_bfd = abfd->archive_head;
5718
5719 /* Some initialization. */
5720 *num_syms = 0;
5721 *stringsize = 0;
5722
5723 /* Iterate over each BFD within this archive. */
5724 while (curr_bfd != NULL)
5725 {
5726 unsigned int curr_count, i;
5727 som_symbol_type *sym;
5728
5729 /* Don't bother for non-SOM objects. */
5730 if (curr_bfd->format != bfd_object
5731 || curr_bfd->xvec->flavour != bfd_target_som_flavour)
5732 {
5733 curr_bfd = curr_bfd->next;
5734 continue;
5735 }
5736
5737 /* Make sure the symbol table has been read, then snag a pointer
5738 to it. It's a little slimey to grab the symbols via obj_som_symtab,
5739 but doing so avoids allocating lots of extra memory. */
82e51918 5740 if (! som_slurp_symbol_table (curr_bfd))
b34976b6 5741 return FALSE;
252b5132
RH
5742
5743 sym = obj_som_symtab (curr_bfd);
5744 curr_count = bfd_get_symcount (curr_bfd);
5745
5746 /* Examine each symbol to determine if it belongs in the
5747 library symbol table. */
5748 for (i = 0; i < curr_count; i++, sym++)
5749 {
5750 struct som_misc_symbol_info info;
5751
5752 /* Derive SOM information from the BFD symbol. */
5753 som_bfd_derive_misc_symbol_info (curr_bfd, &sym->symbol, &info);
5754
5755 /* Should we include this symbol? */
5756 if (info.symbol_type == ST_NULL
5757 || info.symbol_type == ST_SYM_EXT
5758 || info.symbol_type == ST_ARG_EXT)
5759 continue;
5760
5761 /* Only global symbols and unsatisfied commons. */
5762 if (info.symbol_scope != SS_UNIVERSAL
5763 && info.symbol_type != ST_STORAGE)
5764 continue;
5765
5766 /* Do no include undefined symbols. */
5767 if (bfd_is_und_section (sym->symbol.section))
5768 continue;
5769
5770 /* Bump the various counters, being careful to honor
5771 alignment considerations in the string table. */
5772 (*num_syms)++;
5773 *stringsize = *stringsize + strlen (sym->symbol.name) + 5;
5774 while (*stringsize % 4)
5775 (*stringsize)++;
5776 }
5777
5778 curr_bfd = curr_bfd->next;
5779 }
b34976b6 5780 return TRUE;
252b5132
RH
5781}
5782
5783/* Hash a symbol name based on the hashing algorithm presented in the
5784 SOM ABI. */
7eae7d22 5785
252b5132 5786static unsigned int
116c20d2 5787som_bfd_ar_symbol_hash (asymbol *symbol)
252b5132
RH
5788{
5789 unsigned int len = strlen (symbol->name);
5790
5791 /* Names with length 1 are special. */
5792 if (len == 1)
5793 return 0x1000100 | (symbol->name[0] << 16) | symbol->name[0];
5794
5795 return ((len & 0x7f) << 24) | (symbol->name[1] << 16)
7eae7d22 5796 | (symbol->name[len - 2] << 8) | symbol->name[len - 1];
252b5132
RH
5797}
5798
5799/* Do the bulk of the work required to write the SOM library
5800 symbol table. */
6fa957a9 5801
b34976b6 5802static bfd_boolean
116c20d2
NC
5803som_bfd_ar_write_symbol_stuff (bfd *abfd,
5804 unsigned int nsyms,
5805 unsigned int string_size,
5806 struct lst_header lst,
5807 unsigned elength)
252b5132
RH
5808{
5809 file_ptr lst_filepos;
5810 char *strings = NULL, *p;
5811 struct lst_symbol_record *lst_syms = NULL, *curr_lst_sym;
5812 bfd *curr_bfd;
5813 unsigned int *hash_table = NULL;
5814 struct som_entry *som_dict = NULL;
5815 struct lst_symbol_record **last_hash_entry = NULL;
5816 unsigned int curr_som_offset, som_index = 0;
dc810e39 5817 bfd_size_type amt;
252b5132 5818
dc810e39
AM
5819 amt = lst.hash_size;
5820 amt *= sizeof (unsigned int);
116c20d2 5821 hash_table = bfd_zmalloc (amt);
252b5132
RH
5822 if (hash_table == NULL && lst.hash_size != 0)
5823 goto error_return;
dc810e39
AM
5824
5825 amt = lst.module_count;
5826 amt *= sizeof (struct som_entry);
116c20d2 5827 som_dict = bfd_zmalloc (amt);
252b5132
RH
5828 if (som_dict == NULL && lst.module_count != 0)
5829 goto error_return;
5830
dc810e39
AM
5831 amt = lst.hash_size;
5832 amt *= sizeof (struct lst_symbol_record *);
116c20d2 5833 last_hash_entry = bfd_zmalloc (amt);
252b5132
RH
5834 if (last_hash_entry == NULL && lst.hash_size != 0)
5835 goto error_return;
5836
5837 /* Lots of fields are file positions relative to the start
5838 of the lst record. So save its location. */
5839 lst_filepos = bfd_tell (abfd) - sizeof (struct lst_header);
5840
252b5132
RH
5841 /* Symbols have som_index fields, so we have to keep track of the
5842 index of each SOM in the archive.
5843
5844 The SOM dictionary has (among other things) the absolute file
5845 position for the SOM which a particular dictionary entry
5846 describes. We have to compute that information as we iterate
5847 through the SOMs/symbols. */
5848 som_index = 0;
5849
5850 /* We add in the size of the archive header twice as the location
5851 in the SOM dictionary is the actual offset of the SOM, not the
5852 archive header before the SOM. */
5853 curr_som_offset = 8 + 2 * sizeof (struct ar_hdr) + lst.file_end;
5854
5855 /* Make room for the archive header and the contents of the
5856 extended string table. Note that elength includes the size
5857 of the archive header for the extended name table! */
5858 if (elength)
5859 curr_som_offset += elength;
5860
5861 /* Make sure we're properly aligned. */
5862 curr_som_offset = (curr_som_offset + 0x1) & ~0x1;
5863
6fa957a9 5864 /* FIXME should be done with buffers just like everything else... */
dc810e39
AM
5865 amt = nsyms;
5866 amt *= sizeof (struct lst_symbol_record);
5867 lst_syms = bfd_malloc (amt);
252b5132
RH
5868 if (lst_syms == NULL && nsyms != 0)
5869 goto error_return;
dc810e39 5870 strings = bfd_malloc ((bfd_size_type) string_size);
252b5132
RH
5871 if (strings == NULL && string_size != 0)
5872 goto error_return;
5873
5874 p = strings;
5875 curr_lst_sym = lst_syms;
5876
5877 curr_bfd = abfd->archive_head;
5878 while (curr_bfd != NULL)
5879 {
5880 unsigned int curr_count, i;
5881 som_symbol_type *sym;
5882
5883 /* Don't bother for non-SOM objects. */
5884 if (curr_bfd->format != bfd_object
5885 || curr_bfd->xvec->flavour != bfd_target_som_flavour)
5886 {
5887 curr_bfd = curr_bfd->next;
5888 continue;
5889 }
5890
5891 /* Make sure the symbol table has been read, then snag a pointer
5892 to it. It's a little slimey to grab the symbols via obj_som_symtab,
5893 but doing so avoids allocating lots of extra memory. */
82e51918 5894 if (! som_slurp_symbol_table (curr_bfd))
252b5132
RH
5895 goto error_return;
5896
5897 sym = obj_som_symtab (curr_bfd);
5898 curr_count = bfd_get_symcount (curr_bfd);
5899
5900 for (i = 0; i < curr_count; i++, sym++)
5901 {
5902 struct som_misc_symbol_info info;
5903
5904 /* Derive SOM information from the BFD symbol. */
5905 som_bfd_derive_misc_symbol_info (curr_bfd, &sym->symbol, &info);
5906
5907 /* Should we include this symbol? */
5908 if (info.symbol_type == ST_NULL
5909 || info.symbol_type == ST_SYM_EXT
5910 || info.symbol_type == ST_ARG_EXT)
5911 continue;
5912
5913 /* Only global symbols and unsatisfied commons. */
5914 if (info.symbol_scope != SS_UNIVERSAL
5915 && info.symbol_type != ST_STORAGE)
5916 continue;
5917
5918 /* Do no include undefined symbols. */
5919 if (bfd_is_und_section (sym->symbol.section))
5920 continue;
5921
5922 /* If this is the first symbol from this SOM, then update
5923 the SOM dictionary too. */
5924 if (som_dict[som_index].location == 0)
5925 {
5926 som_dict[som_index].location = curr_som_offset;
5927 som_dict[som_index].length = arelt_size (curr_bfd);
5928 }
5929
5930 /* Fill in the lst symbol record. */
5931 curr_lst_sym->hidden = 0;
ba20314e 5932 curr_lst_sym->secondary_def = info.secondary_def;
252b5132
RH
5933 curr_lst_sym->symbol_type = info.symbol_type;
5934 curr_lst_sym->symbol_scope = info.symbol_scope;
5935 curr_lst_sym->check_level = 0;
5936 curr_lst_sym->must_qualify = 0;
5937 curr_lst_sym->initially_frozen = 0;
5938 curr_lst_sym->memory_resident = 0;
5939 curr_lst_sym->is_common = bfd_is_com_section (sym->symbol.section);
351e2b5a 5940 curr_lst_sym->dup_common = info.dup_common;
252b5132
RH
5941 curr_lst_sym->xleast = 3;
5942 curr_lst_sym->arg_reloc = info.arg_reloc;
5943 curr_lst_sym->name.n_strx = p - strings + 4;
5944 curr_lst_sym->qualifier_name.n_strx = 0;
5945 curr_lst_sym->symbol_info = info.symbol_info;
5946 curr_lst_sym->symbol_value = info.symbol_value | info.priv_level;
5947 curr_lst_sym->symbol_descriptor = 0;
5948 curr_lst_sym->reserved = 0;
5949 curr_lst_sym->som_index = som_index;
5950 curr_lst_sym->symbol_key = som_bfd_ar_symbol_hash (&sym->symbol);
5951 curr_lst_sym->next_entry = 0;
5952
5953 /* Insert into the hash table. */
5954 if (hash_table[curr_lst_sym->symbol_key % lst.hash_size])
5955 {
5956 struct lst_symbol_record *tmp;
5957
5958 /* There is already something at the head of this hash chain,
5959 so tack this symbol onto the end of the chain. */
5960 tmp = last_hash_entry[curr_lst_sym->symbol_key % lst.hash_size];
5961 tmp->next_entry
5962 = (curr_lst_sym - lst_syms) * sizeof (struct lst_symbol_record)
6fa957a9 5963 + lst.hash_size * 4
252b5132
RH
5964 + lst.module_count * sizeof (struct som_entry)
5965 + sizeof (struct lst_header);
5966 }
5967 else
116c20d2
NC
5968 /* First entry in this hash chain. */
5969 hash_table[curr_lst_sym->symbol_key % lst.hash_size]
5970 = (curr_lst_sym - lst_syms) * sizeof (struct lst_symbol_record)
5971 + lst.hash_size * 4
5972 + lst.module_count * sizeof (struct som_entry)
5973 + sizeof (struct lst_header);
252b5132
RH
5974
5975 /* Keep track of the last symbol we added to this chain so we can
5976 easily update its next_entry pointer. */
5977 last_hash_entry[curr_lst_sym->symbol_key % lst.hash_size]
5978 = curr_lst_sym;
5979
252b5132
RH
5980 /* Update the string table. */
5981 bfd_put_32 (abfd, strlen (sym->symbol.name), p);
5982 p += 4;
5983 strcpy (p, sym->symbol.name);
5984 p += strlen (sym->symbol.name) + 1;
7eae7d22 5985 while ((int) p % 4)
252b5132
RH
5986 {
5987 bfd_put_8 (abfd, 0, p);
5988 p++;
5989 }
5990
5991 /* Head to the next symbol. */
5992 curr_lst_sym++;
5993 }
5994
5995 /* Keep track of where each SOM will finally reside; then look
5996 at the next BFD. */
5997 curr_som_offset += arelt_size (curr_bfd) + sizeof (struct ar_hdr);
6fa957a9 5998
252b5132
RH
5999 /* A particular object in the archive may have an odd length; the
6000 linker requires objects begin on an even boundary. So round
6001 up the current offset as necessary. */
dc810e39 6002 curr_som_offset = (curr_som_offset + 0x1) &~ (unsigned) 1;
252b5132
RH
6003 curr_bfd = curr_bfd->next;
6004 som_index++;
6005 }
6006
6007 /* Now scribble out the hash table. */
dc810e39 6008 amt = lst.hash_size * 4;
116c20d2 6009 if (bfd_bwrite ((void *) hash_table, amt, abfd) != amt)
252b5132
RH
6010 goto error_return;
6011
6012 /* Then the SOM dictionary. */
dc810e39 6013 amt = lst.module_count * sizeof (struct som_entry);
116c20d2 6014 if (bfd_bwrite ((void *) som_dict, amt, abfd) != amt)
252b5132
RH
6015 goto error_return;
6016
6017 /* The library symbols. */
dc810e39 6018 amt = nsyms * sizeof (struct lst_symbol_record);
116c20d2 6019 if (bfd_bwrite ((void *) lst_syms, amt, abfd) != amt)
252b5132
RH
6020 goto error_return;
6021
6022 /* And finally the strings. */
dc810e39 6023 amt = string_size;
116c20d2 6024 if (bfd_bwrite ((void *) strings, amt, abfd) != amt)
252b5132
RH
6025 goto error_return;
6026
6027 if (hash_table != NULL)
6028 free (hash_table);
6029 if (som_dict != NULL)
6030 free (som_dict);
6031 if (last_hash_entry != NULL)
6032 free (last_hash_entry);
6033 if (lst_syms != NULL)
6034 free (lst_syms);
6035 if (strings != NULL)
6036 free (strings);
b34976b6 6037 return TRUE;
252b5132
RH
6038
6039 error_return:
6040 if (hash_table != NULL)
6041 free (hash_table);
6042 if (som_dict != NULL)
6043 free (som_dict);
6044 if (last_hash_entry != NULL)
6045 free (last_hash_entry);
6046 if (lst_syms != NULL)
6047 free (lst_syms);
6048 if (strings != NULL)
6049 free (strings);
6050
b34976b6 6051 return FALSE;
252b5132
RH
6052}
6053
6054/* Write out the LST for the archive.
6055
6056 You'll never believe this is really how armaps are handled in SOM... */
6057
b34976b6 6058static bfd_boolean
116c20d2
NC
6059som_write_armap (bfd *abfd,
6060 unsigned int elength,
6061 struct orl *map ATTRIBUTE_UNUSED,
6062 unsigned int orl_count ATTRIBUTE_UNUSED,
6063 int stridx ATTRIBUTE_UNUSED)
252b5132
RH
6064{
6065 bfd *curr_bfd;
6066 struct stat statbuf;
6067 unsigned int i, lst_size, nsyms, stringsize;
6068 struct ar_hdr hdr;
6069 struct lst_header lst;
6070 int *p;
dc810e39 6071 bfd_size_type amt;
6fa957a9 6072
252b5132
RH
6073 /* We'll use this for the archive's date and mode later. */
6074 if (stat (abfd->filename, &statbuf) != 0)
6075 {
6076 bfd_set_error (bfd_error_system_call);
b34976b6 6077 return FALSE;
252b5132
RH
6078 }
6079 /* Fudge factor. */
6080 bfd_ardata (abfd)->armap_timestamp = statbuf.st_mtime + 60;
6081
6082 /* Account for the lst header first. */
6083 lst_size = sizeof (struct lst_header);
6084
6085 /* Start building the LST header. */
6086 /* FIXME: Do we need to examine each element to determine the
6087 largest id number? */
6088 lst.system_id = CPU_PA_RISC1_0;
6089 lst.a_magic = LIBMAGIC;
6090 lst.version_id = VERSION_ID;
6091 lst.file_time.secs = 0;
6092 lst.file_time.nanosecs = 0;
6093
6094 lst.hash_loc = lst_size;
6095 lst.hash_size = SOM_LST_HASH_SIZE;
6096
6097 /* Hash table is a SOM_LST_HASH_SIZE 32bit offsets. */
6098 lst_size += 4 * SOM_LST_HASH_SIZE;
6099
6100 /* We need to count the number of SOMs in this archive. */
6101 curr_bfd = abfd->archive_head;
6102 lst.module_count = 0;
6103 while (curr_bfd != NULL)
6104 {
6105 /* Only true SOM objects count. */
6106 if (curr_bfd->format == bfd_object
6107 && curr_bfd->xvec->flavour == bfd_target_som_flavour)
6108 lst.module_count++;
6109 curr_bfd = curr_bfd->next;
6110 }
6111 lst.module_limit = lst.module_count;
6112 lst.dir_loc = lst_size;
6113 lst_size += sizeof (struct som_entry) * lst.module_count;
6114
6115 /* We don't support import/export tables, auxiliary headers,
6116 or free lists yet. Make the linker work a little harder
6117 to make our life easier. */
6118
6119 lst.export_loc = 0;
6120 lst.export_count = 0;
6121 lst.import_loc = 0;
6122 lst.aux_loc = 0;
6123 lst.aux_size = 0;
6124
6125 /* Count how many symbols we will have on the hash chains and the
6126 size of the associated string table. */
82e51918 6127 if (! som_bfd_prep_for_ar_write (abfd, &nsyms, &stringsize))
b34976b6 6128 return FALSE;
252b5132
RH
6129
6130 lst_size += sizeof (struct lst_symbol_record) * nsyms;
6131
6132 /* For the string table. One day we might actually use this info
6133 to avoid small seeks/reads when reading archives. */
6134 lst.string_loc = lst_size;
6135 lst.string_size = stringsize;
6136 lst_size += stringsize;
6137
6138 /* SOM ABI says this must be zero. */
6139 lst.free_list = 0;
6140 lst.file_end = lst_size;
6141
6142 /* Compute the checksum. Must happen after the entire lst header
6143 has filled in. */
7eae7d22 6144 p = (int *) &lst;
252b5132 6145 lst.checksum = 0;
7eae7d22 6146 for (i = 0; i < sizeof (struct lst_header) / sizeof (int) - 1; i++)
252b5132
RH
6147 lst.checksum ^= *p++;
6148
6149 sprintf (hdr.ar_name, "/ ");
6150 sprintf (hdr.ar_date, "%ld", bfd_ardata (abfd)->armap_timestamp);
6151 sprintf (hdr.ar_uid, "%ld", (long) getuid ());
6152 sprintf (hdr.ar_gid, "%ld", (long) getgid ());
6153 sprintf (hdr.ar_mode, "%-8o", (unsigned int) statbuf.st_mode);
6154 sprintf (hdr.ar_size, "%-10d", (int) lst_size);
6155 hdr.ar_fmag[0] = '`';
6156 hdr.ar_fmag[1] = '\012';
6157
6158 /* Turn any nulls into spaces. */
6159 for (i = 0; i < sizeof (struct ar_hdr); i++)
6160 if (((char *) (&hdr))[i] == '\0')
6161 (((char *) (&hdr))[i]) = ' ';
6162
6163 /* Scribble out the ar header. */
dc810e39 6164 amt = sizeof (struct ar_hdr);
116c20d2 6165 if (bfd_bwrite ((void *) &hdr, amt, abfd) != amt)
b34976b6 6166 return FALSE;
252b5132
RH
6167
6168 /* Now scribble out the lst header. */
dc810e39 6169 amt = sizeof (struct lst_header);
116c20d2 6170 if (bfd_bwrite ((void *) &lst, amt, abfd) != amt)
b34976b6 6171 return FALSE;
252b5132
RH
6172
6173 /* Build and write the armap. */
dc810e39 6174 if (!som_bfd_ar_write_symbol_stuff (abfd, nsyms, stringsize, lst, elength))
b34976b6 6175 return FALSE;
6fa957a9 6176
252b5132 6177 /* Done. */
b34976b6 6178 return TRUE;
252b5132
RH
6179}
6180
6181/* Free all information we have cached for this BFD. We can always
6182 read it again later if we need it. */
6183
b34976b6 6184static bfd_boolean
116c20d2 6185som_bfd_free_cached_info (bfd *abfd)
252b5132
RH
6186{
6187 asection *o;
6188
6189 if (bfd_get_format (abfd) != bfd_object)
b34976b6 6190 return TRUE;
252b5132
RH
6191
6192#define FREE(x) if (x != NULL) { free (x); x = NULL; }
6193 /* Free the native string and symbol tables. */
6194 FREE (obj_som_symtab (abfd));
6195 FREE (obj_som_stringtab (abfd));
116c20d2 6196 for (o = abfd->sections; o != NULL; o = o->next)
252b5132
RH
6197 {
6198 /* Free the native relocations. */
dc810e39 6199 o->reloc_count = (unsigned) -1;
252b5132
RH
6200 FREE (som_section_data (o)->reloc_stream);
6201 /* Free the generic relocations. */
6202 FREE (o->relocation);
6203 }
6204#undef FREE
6205
b34976b6 6206 return TRUE;
252b5132
RH
6207}
6208
6fa957a9 6209/* End of miscellaneous support functions. */
252b5132
RH
6210
6211/* Linker support functions. */
7eae7d22 6212
b34976b6 6213static bfd_boolean
116c20d2 6214som_bfd_link_split_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
252b5132 6215{
116c20d2 6216 return som_is_subspace (sec) && sec->size > 240000;
252b5132
RH
6217}
6218
116c20d2
NC
6219#define som_close_and_cleanup som_bfd_free_cached_info
6220#define som_read_ar_hdr _bfd_generic_read_ar_hdr
6221#define som_openr_next_archived_file bfd_generic_openr_next_archived_file
6222#define som_get_elt_at_index _bfd_generic_get_elt_at_index
6223#define som_generic_stat_arch_elt bfd_generic_stat_arch_elt
6224#define som_truncate_arname bfd_bsd_truncate_arname
6225#define som_slurp_extended_name_table _bfd_slurp_extended_name_table
6226#define som_construct_extended_name_table _bfd_archive_coff_construct_extended_name_table
6227#define som_update_armap_timestamp bfd_true
6228#define som_bfd_is_target_special_symbol ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
6229#define som_get_lineno _bfd_nosymbols_get_lineno
6230#define som_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
6231#define som_read_minisymbols _bfd_generic_read_minisymbols
6232#define som_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
6233#define som_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
6234#define som_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
6235#define som_bfd_relax_section bfd_generic_relax_section
6236#define som_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
6237#define som_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
6238#define som_bfd_link_add_symbols _bfd_generic_link_add_symbols
6239#define som_bfd_link_just_syms _bfd_generic_link_just_syms
6240#define som_bfd_final_link _bfd_generic_final_link
6241#define som_bfd_gc_sections bfd_generic_gc_sections
6242#define som_bfd_merge_sections bfd_generic_merge_sections
6243#define som_bfd_is_group_section bfd_generic_is_group_section
6244#define som_bfd_discard_group bfd_generic_discard_group
6245#define som_section_already_linked _bfd_generic_section_already_linked
6a808a40
MK
6246#define som_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data
6247#define som_bfd_copy_private_header_data _bfd_generic_bfd_copy_private_header_data
6248#define som_bfd_set_private_flags _bfd_generic_bfd_set_private_flags
116c20d2
NC
6249
6250const bfd_target som_vec =
6251{
6252 "som", /* Name. */
252b5132 6253 bfd_target_som_flavour,
116c20d2
NC
6254 BFD_ENDIAN_BIG, /* Target byte order. */
6255 BFD_ENDIAN_BIG, /* Target headers byte order. */
6256 (HAS_RELOC | EXEC_P | /* Object flags. */
252b5132
RH
6257 HAS_LINENO | HAS_DEBUG |
6258 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED | DYNAMIC),
351e2b5a 6259 (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS | SEC_LINK_ONCE
116c20d2 6260 | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* Section flags. */
252b5132 6261
116c20d2
NC
6262 /* Leading_symbol_char: is the first char of a user symbol
6263 predictable, and if so what is it. */
252b5132 6264 0,
116c20d2
NC
6265 '/', /* AR_pad_char. */
6266 14, /* AR_max_namelen. */
252b5132
RH
6267 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
6268 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
116c20d2 6269 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Data. */
252b5132
RH
6270 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
6271 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
116c20d2 6272 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Headers. */
252b5132 6273 {_bfd_dummy_target,
116c20d2 6274 som_object_p, /* bfd_check_format. */
252b5132
RH
6275 bfd_generic_archive_p,
6276 _bfd_dummy_target
6277 },
6278 {
6279 bfd_false,
6280 som_mkobject,
6281 _bfd_generic_mkarchive,
6282 bfd_false
6283 },
6284 {
6285 bfd_false,
6286 som_write_object_contents,
6287 _bfd_write_archive_contents,
6288 bfd_false,
6289 },
6290#undef som
6291
6292 BFD_JUMP_TABLE_GENERIC (som),
6293 BFD_JUMP_TABLE_COPY (som),
6294 BFD_JUMP_TABLE_CORE (_bfd_nocore),
6295 BFD_JUMP_TABLE_ARCHIVE (som),
6296 BFD_JUMP_TABLE_SYMBOLS (som),
6297 BFD_JUMP_TABLE_RELOCS (som),
6298 BFD_JUMP_TABLE_WRITE (som),
6299 BFD_JUMP_TABLE_LINK (som),
6300 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
6301
c3c89269 6302 NULL,
6fa957a9 6303
116c20d2 6304 NULL
252b5132
RH
6305};
6306
6307#endif /* HOST_HPPAHPUX || HOST_HPPABSD || HOST_HPPAOSF */
This page took 0.639925 seconds and 4 git commands to generate.