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