Convert to ISO C90 formatting
[deliverable/binutils-gdb.git] / bfd / nlm32-ppc.c
CommitLineData
252b5132 1/* Support for 32-bit PowerPC NLM (NetWare Loadable Module)
9553c638 2 Copyright 1994, 1995, 1999, 2000, 2001, 2002, 2003, 2004
0f867abe 3 Free Software Foundation, Inc.
252b5132
RH
4
5This file is part of BFD, the Binary File Descriptor library.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
21#include "bfd.h"
22#include "sysdep.h"
23#include "libbfd.h"
24
25/* The format of a PowerPC NLM changed. Define OLDFORMAT to get the
26 old format. */
27
28#define ARCH_SIZE 32
29
30#include "nlm/ppc-ext.h"
31#define Nlm_External_Fixed_Header Nlm32_powerpc_External_Fixed_Header
32
33#include "libnlm.h"
34
35#ifdef OLDFORMAT
b34976b6 36static bfd_boolean nlm_powerpc_backend_object_p
252b5132 37 PARAMS ((bfd *));
b34976b6 38static bfd_boolean nlm_powerpc_write_prefix
252b5132
RH
39 PARAMS ((bfd *));
40#endif
41
b34976b6 42static bfd_boolean nlm_powerpc_read_reloc
252b5132 43 PARAMS ((bfd *, nlmNAME(symbol_type) *, asection **, arelent *));
b34976b6 44static bfd_boolean nlm_powerpc_mangle_relocs
0f867abe 45 PARAMS ((bfd *, asection *, const PTR, bfd_vma, bfd_size_type));
b34976b6 46static bfd_boolean nlm_powerpc_read_import
252b5132
RH
47 PARAMS ((bfd *, nlmNAME(symbol_type) *));
48
49#ifdef OLDFORMAT
b34976b6 50static bfd_boolean nlm_powerpc_write_reloc
252b5132
RH
51 PARAMS ((bfd *, asection *, arelent *, int));
52#endif
53
b34976b6 54static bfd_boolean nlm_powerpc_write_import
252b5132 55 PARAMS ((bfd *, asection *, arelent *));
b34976b6 56static bfd_boolean nlm_powerpc_write_external
252b5132
RH
57 PARAMS ((bfd *, bfd_size_type, asymbol *, struct reloc_and_sec *));
58
59#ifndef OLDFORMAT
b34976b6 60static bfd_boolean nlm_powerpc_set_public_section
252b5132
RH
61 PARAMS ((bfd *, nlmNAME(symbol_type) *));
62static bfd_vma nlm_powerpc_get_public_offset
63 PARAMS ((bfd *, asymbol *));
64#endif
65\f
66#ifdef OLDFORMAT
67
68/* The prefix header is only used in the old format. */
69
70/* PowerPC NLM's have a prefix header before the standard NLM. This
71 function reads it in, verifies the version, and seeks the bfd to
72 the location before the regular NLM header. */
73
b34976b6 74static bfd_boolean
252b5132
RH
75nlm_powerpc_backend_object_p (abfd)
76 bfd *abfd;
77{
78 struct nlm32_powerpc_external_prefix_header s;
79
dc810e39 80 if (bfd_bread ((PTR) &s, (bfd_size_type) sizeof s, abfd) != sizeof s)
b34976b6 81 return FALSE;
252b5132
RH
82
83 if (memcmp (s.signature, NLM32_POWERPC_SIGNATURE, sizeof s.signature) != 0
dc810e39 84 || H_GET_32 (abfd, s.headerVersion) != NLM32_POWERPC_HEADER_VERSION)
b34976b6 85 return FALSE;
252b5132 86
b34976b6 87 return TRUE;
252b5132
RH
88}
89
90/* Write out the prefix. */
91
b34976b6 92static bfd_boolean
252b5132
RH
93nlm_powerpc_write_prefix (abfd)
94 bfd *abfd;
95{
96 struct nlm32_powerpc_external_prefix_header s;
97
98 memset (&s, 0, sizeof s);
99 memcpy (s.signature, NLM32_POWERPC_SIGNATURE, sizeof s.signature);
dc810e39
AM
100 H_PUT_32 (abfd, NLM32_POWERPC_HEADER_VERSION, s.headerVersion);
101 H_PUT_32 (abfd, 0, s.origins);
252b5132
RH
102
103 /* FIXME: What should we do about the date? */
104
dc810e39 105 if (bfd_bwrite ((PTR) &s, (bfd_size_type) sizeof s, abfd) != sizeof s)
b34976b6 106 return FALSE;
252b5132 107
b34976b6 108 return TRUE;
252b5132
RH
109}
110
111#endif /* OLDFORMAT */
112\f
113#ifndef OLDFORMAT
114
115/* There is only one type of reloc in a PowerPC NLM. */
116
117static reloc_howto_type nlm_powerpc_howto =
118 HOWTO (0, /* type */
119 0, /* rightshift */
120 2, /* size (0 = byte, 1 = short, 2 = long) */
121 32, /* bitsize */
b34976b6 122 FALSE, /* pc_relative */
252b5132
RH
123 0, /* bitpos */
124 complain_overflow_bitfield, /* complain_on_overflow */
125 0, /* special_function */
126 "32", /* name */
b34976b6 127 TRUE, /* partial_inplace */
252b5132
RH
128 0xffffffff, /* src_mask */
129 0xffffffff, /* dst_mask */
b34976b6 130 FALSE); /* pcrel_offset */
252b5132
RH
131
132/* Read a PowerPC NLM reloc. */
133
b34976b6 134static bfd_boolean
252b5132
RH
135nlm_powerpc_read_reloc (abfd, sym, secp, rel)
136 bfd *abfd;
137 nlmNAME(symbol_type) *sym;
138 asection **secp;
139 arelent *rel;
140{
141 bfd_byte temp[4];
142 bfd_vma val;
143 const char *name;
144
dc810e39 145 if (bfd_bread (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp))
b34976b6 146 return FALSE;
252b5132
RH
147
148 val = bfd_get_32 (abfd, temp);
149
150 /* The value is a word offset into either the code or data segment.
151 This is the location which needs to be adjusted.
152
153 The high bit is 0 if the value is an offset into the data
154 segment, or 1 if the value is an offset into the text segment.
155
156 If this is a relocation fixup rather than an imported symbol (the
157 sym argument is NULL), then the second most significant bit is 0
158 if the address of the data segment should be added to the
159 location addressed by the value, or 1 if the address of the text
160 segment should be added.
161
162 If this is an imported symbol, the second most significant bit is
163 not used and must be 0. */
164
165 if ((val & NLM_HIBIT) == 0)
166 name = NLM_INITIALIZED_DATA_NAME;
167 else
168 {
169 name = NLM_CODE_NAME;
170 val &=~ NLM_HIBIT;
171 }
172 *secp = bfd_get_section_by_name (abfd, name);
173
174 if (sym == NULL)
175 {
176 if ((val & (NLM_HIBIT >> 1)) == 0)
177 name = NLM_INITIALIZED_DATA_NAME;
178 else
179 {
180 name = NLM_CODE_NAME;
181 val &=~ (NLM_HIBIT >> 1);
182 }
183 rel->sym_ptr_ptr = bfd_get_section_by_name (abfd, name)->symbol_ptr_ptr;
184 }
185
186 rel->howto = &nlm_powerpc_howto;
187
188 rel->address = val << 2;
189 rel->addend = 0;
190
b34976b6 191 return TRUE;
252b5132
RH
192}
193
194#else /* OLDFORMAT */
195
196/* This reloc handling is only applicable to the old format. */
197
198/* How to process the various reloc types. PowerPC NLMs use XCOFF
199 reloc types, and I have just copied the XCOFF reloc table here. */
200
201static reloc_howto_type nlm_powerpc_howto_table[] =
202{
203 /* Standard 32 bit relocation. */
1518639e
KH
204 HOWTO (0, /* type */
205 0, /* rightshift */
206 2, /* size (0 = byte, 1 = short, 2 = long) */
207 32, /* bitsize */
b34976b6 208 FALSE, /* pc_relative */
1518639e 209 0, /* bitpos */
252b5132 210 complain_overflow_bitfield, /* complain_on_overflow */
1518639e
KH
211 0, /* special_function */
212 "R_POS", /* name */
b34976b6 213 TRUE, /* partial_inplace */
1518639e
KH
214 0xffffffff, /* src_mask */
215 0xffffffff, /* dst_mask */
b34976b6 216 FALSE), /* pcrel_offset */
252b5132
RH
217
218 /* 32 bit relocation, but store negative value. */
1518639e
KH
219 HOWTO (1, /* type */
220 0, /* rightshift */
221 -2, /* size (0 = byte, 1 = short, 2 = long) */
222 32, /* bitsize */
b34976b6 223 FALSE, /* pc_relative */
1518639e 224 0, /* bitpos */
252b5132 225 complain_overflow_bitfield, /* complain_on_overflow */
1518639e
KH
226 0, /* special_function */
227 "R_NEG", /* name */
b34976b6 228 TRUE, /* partial_inplace */
1518639e
KH
229 0xffffffff, /* src_mask */
230 0xffffffff, /* dst_mask */
b34976b6 231 FALSE), /* pcrel_offset */
252b5132
RH
232
233 /* 32 bit PC relative relocation. */
1518639e
KH
234 HOWTO (2, /* type */
235 0, /* rightshift */
236 2, /* size (0 = byte, 1 = short, 2 = long) */
237 32, /* bitsize */
b34976b6 238 TRUE, /* pc_relative */
1518639e 239 0, /* bitpos */
252b5132 240 complain_overflow_signed, /* complain_on_overflow */
1518639e
KH
241 0, /* special_function */
242 "R_REL", /* name */
b34976b6 243 TRUE, /* partial_inplace */
1518639e
KH
244 0xffffffff, /* src_mask */
245 0xffffffff, /* dst_mask */
b34976b6 246 FALSE), /* pcrel_offset */
1518639e 247
252b5132 248 /* 16 bit TOC relative relocation. */
1518639e
KH
249 HOWTO (3, /* type */
250 0, /* rightshift */
251 1, /* size (0 = byte, 1 = short, 2 = long) */
252 16, /* bitsize */
b34976b6 253 FALSE, /* pc_relative */
1518639e 254 0, /* bitpos */
252b5132 255 complain_overflow_signed, /* complain_on_overflow */
1518639e
KH
256 0, /* special_function */
257 "R_TOC", /* name */
b34976b6 258 TRUE, /* partial_inplace */
1518639e
KH
259 0xffff, /* src_mask */
260 0xffff, /* dst_mask */
b34976b6 261 FALSE), /* pcrel_offset */
1518639e 262
252b5132 263 /* I don't really know what this is. */
1518639e
KH
264 HOWTO (4, /* type */
265 1, /* rightshift */
266 2, /* size (0 = byte, 1 = short, 2 = long) */
267 32, /* bitsize */
b34976b6 268 FALSE, /* pc_relative */
1518639e 269 0, /* bitpos */
252b5132 270 complain_overflow_bitfield, /* complain_on_overflow */
1518639e
KH
271 0, /* special_function */
272 "R_RTB", /* name */
b34976b6 273 TRUE, /* partial_inplace */
1518639e
KH
274 0xffffffff, /* src_mask */
275 0xffffffff, /* dst_mask */
b34976b6 276 FALSE), /* pcrel_offset */
1518639e 277
252b5132 278 /* External TOC relative symbol. */
1518639e
KH
279 HOWTO (5, /* type */
280 0, /* rightshift */
281 2, /* size (0 = byte, 1 = short, 2 = long) */
282 16, /* bitsize */
b34976b6 283 FALSE, /* pc_relative */
1518639e 284 0, /* bitpos */
252b5132 285 complain_overflow_bitfield, /* complain_on_overflow */
1518639e
KH
286 0, /* special_function */
287 "R_GL", /* name */
b34976b6 288 TRUE, /* partial_inplace */
1518639e
KH
289 0xffff, /* src_mask */
290 0xffff, /* dst_mask */
b34976b6 291 FALSE), /* pcrel_offset */
1518639e 292
252b5132 293 /* Local TOC relative symbol. */
1518639e
KH
294 HOWTO (6, /* type */
295 0, /* rightshift */
296 2, /* size (0 = byte, 1 = short, 2 = long) */
297 16, /* bitsize */
b34976b6 298 FALSE, /* pc_relative */
1518639e 299 0, /* bitpos */
252b5132 300 complain_overflow_bitfield, /* complain_on_overflow */
1518639e
KH
301 0, /* special_function */
302 "R_TCL", /* name */
b34976b6 303 TRUE, /* partial_inplace */
1518639e
KH
304 0xffff, /* src_mask */
305 0xffff, /* dst_mask */
b34976b6 306 FALSE), /* pcrel_offset */
1518639e 307
252b5132 308 { 7 },
1518639e 309
252b5132 310 /* Non modifiable absolute branch. */
1518639e
KH
311 HOWTO (8, /* type */
312 0, /* rightshift */
313 2, /* size (0 = byte, 1 = short, 2 = long) */
314 26, /* bitsize */
b34976b6 315 FALSE, /* pc_relative */
1518639e 316 0, /* bitpos */
252b5132 317 complain_overflow_bitfield, /* complain_on_overflow */
1518639e
KH
318 0, /* special_function */
319 "R_BA", /* name */
b34976b6 320 TRUE, /* partial_inplace */
1518639e
KH
321 0x3fffffc, /* src_mask */
322 0x3fffffc, /* dst_mask */
b34976b6 323 FALSE), /* pcrel_offset */
1518639e 324
252b5132
RH
325 { 9 },
326
327 /* Non modifiable relative branch. */
1518639e
KH
328 HOWTO (0xa, /* type */
329 0, /* rightshift */
330 2, /* size (0 = byte, 1 = short, 2 = long) */
331 26, /* bitsize */
b34976b6 332 TRUE, /* pc_relative */
1518639e 333 0, /* bitpos */
252b5132 334 complain_overflow_signed, /* complain_on_overflow */
1518639e
KH
335 0, /* special_function */
336 "R_BR", /* name */
b34976b6 337 TRUE, /* partial_inplace */
1518639e
KH
338 0x3fffffc, /* src_mask */
339 0x3fffffc, /* dst_mask */
b34976b6 340 FALSE), /* pcrel_offset */
1518639e 341
252b5132
RH
342 { 0xb },
343
344 /* Indirect load. */
1518639e
KH
345 HOWTO (0xc, /* type */
346 0, /* rightshift */
347 2, /* size (0 = byte, 1 = short, 2 = long) */
348 16, /* bitsize */
b34976b6 349 FALSE, /* pc_relative */
1518639e 350 0, /* bitpos */
252b5132 351 complain_overflow_bitfield, /* complain_on_overflow */
1518639e
KH
352 0, /* special_function */
353 "R_RL", /* name */
b34976b6 354 TRUE, /* partial_inplace */
1518639e
KH
355 0xffff, /* src_mask */
356 0xffff, /* dst_mask */
b34976b6 357 FALSE), /* pcrel_offset */
1518639e 358
252b5132 359 /* Load address. */
1518639e
KH
360 HOWTO (0xd, /* type */
361 0, /* rightshift */
362 2, /* size (0 = byte, 1 = short, 2 = long) */
363 16, /* bitsize */
b34976b6 364 FALSE, /* pc_relative */
1518639e 365 0, /* bitpos */
252b5132 366 complain_overflow_bitfield, /* complain_on_overflow */
1518639e
KH
367 0, /* special_function */
368 "R_RLA", /* name */
b34976b6 369 TRUE, /* partial_inplace */
1518639e
KH
370 0xffff, /* src_mask */
371 0xffff, /* dst_mask */
b34976b6 372 FALSE), /* pcrel_offset */
1518639e 373
252b5132 374 { 0xe },
1518639e 375
252b5132 376 /* Non-relocating reference. */
1518639e
KH
377 HOWTO (0xf, /* type */
378 0, /* rightshift */
379 2, /* size (0 = byte, 1 = short, 2 = long) */
380 32, /* bitsize */
b34976b6 381 FALSE, /* pc_relative */
1518639e 382 0, /* bitpos */
252b5132 383 complain_overflow_bitfield, /* complain_on_overflow */
1518639e
KH
384 0, /* special_function */
385 "R_REF", /* name */
b34976b6 386 FALSE, /* partial_inplace */
1518639e
KH
387 0, /* src_mask */
388 0, /* dst_mask */
b34976b6 389 FALSE), /* pcrel_offset */
1518639e 390
252b5132
RH
391 { 0x10 },
392 { 0x11 },
1518639e 393
252b5132 394 /* TOC relative indirect load. */
1518639e
KH
395 HOWTO (0x12, /* type */
396 0, /* rightshift */
397 2, /* size (0 = byte, 1 = short, 2 = long) */
398 16, /* bitsize */
b34976b6 399 FALSE, /* pc_relative */
1518639e 400 0, /* bitpos */
252b5132 401 complain_overflow_bitfield, /* complain_on_overflow */
1518639e
KH
402 0, /* special_function */
403 "R_TRL", /* name */
b34976b6 404 TRUE, /* partial_inplace */
1518639e
KH
405 0xffff, /* src_mask */
406 0xffff, /* dst_mask */
b34976b6 407 FALSE), /* pcrel_offset */
1518639e 408
252b5132 409 /* TOC relative load address. */
1518639e
KH
410 HOWTO (0x13, /* type */
411 0, /* rightshift */
412 2, /* size (0 = byte, 1 = short, 2 = long) */
413 16, /* bitsize */
b34976b6 414 FALSE, /* pc_relative */
1518639e 415 0, /* bitpos */
252b5132 416 complain_overflow_bitfield, /* complain_on_overflow */
1518639e
KH
417 0, /* special_function */
418 "R_TRLA", /* name */
b34976b6 419 TRUE, /* partial_inplace */
1518639e
KH
420 0xffff, /* src_mask */
421 0xffff, /* dst_mask */
b34976b6 422 FALSE), /* pcrel_offset */
1518639e 423
252b5132 424 /* Modifiable relative branch. */
1518639e
KH
425 HOWTO (0x14, /* type */
426 1, /* rightshift */
427 2, /* size (0 = byte, 1 = short, 2 = long) */
428 32, /* bitsize */
b34976b6 429 FALSE, /* pc_relative */
1518639e 430 0, /* bitpos */
252b5132 431 complain_overflow_bitfield, /* complain_on_overflow */
1518639e
KH
432 0, /* special_function */
433 "R_RRTBI", /* name */
b34976b6 434 TRUE, /* partial_inplace */
1518639e
KH
435 0xffffffff, /* src_mask */
436 0xffffffff, /* dst_mask */
b34976b6 437 FALSE), /* pcrel_offset */
1518639e 438
252b5132 439 /* Modifiable absolute branch. */
1518639e
KH
440 HOWTO (0x15, /* type */
441 1, /* rightshift */
442 2, /* size (0 = byte, 1 = short, 2 = long) */
443 32, /* bitsize */
b34976b6 444 FALSE, /* pc_relative */
1518639e 445 0, /* bitpos */
252b5132 446 complain_overflow_bitfield, /* complain_on_overflow */
1518639e
KH
447 0, /* special_function */
448 "R_RRTBA", /* name */
b34976b6 449 TRUE, /* partial_inplace */
1518639e
KH
450 0xffffffff, /* src_mask */
451 0xffffffff, /* dst_mask */
b34976b6 452 FALSE), /* pcrel_offset */
1518639e 453
252b5132 454 /* Modifiable call absolute indirect. */
1518639e
KH
455 HOWTO (0x16, /* type */
456 0, /* rightshift */
457 2, /* size (0 = byte, 1 = short, 2 = long) */
458 16, /* bitsize */
b34976b6 459 FALSE, /* pc_relative */
1518639e 460 0, /* bitpos */
252b5132 461 complain_overflow_bitfield, /* complain_on_overflow */
1518639e
KH
462 0, /* special_function */
463 "R_CAI", /* name */
b34976b6 464 TRUE, /* partial_inplace */
1518639e
KH
465 0xffff, /* src_mask */
466 0xffff, /* dst_mask */
b34976b6 467 FALSE), /* pcrel_offset */
1518639e 468
252b5132 469 /* Modifiable call relative. */
1518639e
KH
470 HOWTO (0x17, /* type */
471 0, /* rightshift */
472 2, /* size (0 = byte, 1 = short, 2 = long) */
473 16, /* bitsize */
b34976b6 474 FALSE, /* pc_relative */
1518639e 475 0, /* bitpos */
252b5132 476 complain_overflow_bitfield, /* complain_on_overflow */
1518639e
KH
477 0, /* special_function */
478 "R_REL", /* name */
b34976b6 479 TRUE, /* partial_inplace */
1518639e
KH
480 0xffff, /* src_mask */
481 0xffff, /* dst_mask */
b34976b6 482 FALSE), /* pcrel_offset */
1518639e 483
252b5132 484 /* Modifiable branch absolute. */
1518639e
KH
485 HOWTO (0x18, /* type */
486 0, /* rightshift */
487 2, /* size (0 = byte, 1 = short, 2 = long) */
488 16, /* bitsize */
b34976b6 489 FALSE, /* pc_relative */
1518639e 490 0, /* bitpos */
252b5132 491 complain_overflow_bitfield, /* complain_on_overflow */
1518639e
KH
492 0, /* special_function */
493 "R_RBA", /* name */
b34976b6 494 TRUE, /* partial_inplace */
1518639e
KH
495 0xffff, /* src_mask */
496 0xffff, /* dst_mask */
b34976b6 497 FALSE), /* pcrel_offset */
1518639e 498
252b5132 499 /* Modifiable branch absolute. */
1518639e
KH
500 HOWTO (0x19, /* type */
501 0, /* rightshift */
502 2, /* size (0 = byte, 1 = short, 2 = long) */
503 16, /* bitsize */
b34976b6 504 FALSE, /* pc_relative */
1518639e 505 0, /* bitpos */
252b5132 506 complain_overflow_bitfield, /* complain_on_overflow */
1518639e
KH
507 0, /* special_function */
508 "R_RBAC", /* name */
b34976b6 509 TRUE, /* partial_inplace */
1518639e
KH
510 0xffff, /* src_mask */
511 0xffff, /* dst_mask */
b34976b6 512 FALSE), /* pcrel_offset */
1518639e 513
252b5132 514 /* Modifiable branch relative. */
1518639e
KH
515 HOWTO (0x1a, /* type */
516 0, /* rightshift */
517 2, /* size (0 = byte, 1 = short, 2 = long) */
518 26, /* bitsize */
b34976b6 519 FALSE, /* pc_relative */
1518639e 520 0, /* bitpos */
252b5132 521 complain_overflow_signed, /* complain_on_overflow */
1518639e
KH
522 0, /* special_function */
523 "R_REL", /* name */
b34976b6 524 TRUE, /* partial_inplace */
1518639e
KH
525 0xffff, /* src_mask */
526 0xffff, /* dst_mask */
b34976b6 527 FALSE), /* pcrel_offset */
1518639e 528
252b5132 529 /* Modifiable branch absolute. */
1518639e
KH
530 HOWTO (0x1b, /* type */
531 0, /* rightshift */
532 2, /* size (0 = byte, 1 = short, 2 = long) */
533 16, /* bitsize */
b34976b6 534 FALSE, /* pc_relative */
1518639e 535 0, /* bitpos */
252b5132 536 complain_overflow_bitfield, /* complain_on_overflow */
1518639e
KH
537 0, /* special_function */
538 "R_REL", /* name */
b34976b6 539 TRUE, /* partial_inplace */
1518639e
KH
540 0xffff, /* src_mask */
541 0xffff, /* dst_mask */
b34976b6 542 FALSE) /* pcrel_offset */
252b5132
RH
543};
544
545#define HOWTO_COUNT (sizeof nlm_powerpc_howto_table \
546 / sizeof nlm_powerpc_howto_table[0])
547
548/* Read a PowerPC NLM reloc. */
549
b34976b6 550static bfd_boolean
252b5132
RH
551nlm_powerpc_read_reloc (abfd, sym, secp, rel)
552 bfd *abfd;
553 nlmNAME(symbol_type) *sym;
554 asection **secp;
555 arelent *rel;
556{
557 struct nlm32_powerpc_external_reloc ext;
558 bfd_vma l_vaddr;
559 unsigned long l_symndx;
560 int l_rtype;
561 int l_rsecnm;
562 asection *code_sec, *data_sec, *bss_sec;
563
564 /* Read the reloc from the file. */
dc810e39 565 if (bfd_bread (&ext, (bfd_size_type) sizeof ext, abfd) != sizeof ext)
b34976b6 566 return FALSE;
252b5132
RH
567
568 /* Swap in the fields. */
dc810e39
AM
569 l_vaddr = H_GET_32 (abfd, ext.l_vaddr);
570 l_symndx = H_GET_32 (abfd, ext.l_symndx);
571 l_rtype = H_GET_16 (abfd, ext.l_rtype);
572 l_rsecnm = H_GET_16 (abfd, ext.l_rsecnm);
252b5132
RH
573
574 /* Get the sections now, for convenience. */
575 code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
576 data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
577 bss_sec = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
578
579 /* Work out the arelent fields. */
580 if (sym != NULL)
581 {
582 /* This is an import. sym_ptr_ptr is filled in by
583 nlm_canonicalize_reloc. */
584 rel->sym_ptr_ptr = NULL;
585 }
586 else
587 {
588 asection *sec;
589
590 if (l_symndx == 0)
591 sec = code_sec;
592 else if (l_symndx == 1)
593 sec = data_sec;
594 else if (l_symndx == 2)
595 sec = bss_sec;
596 else
597 {
598 bfd_set_error (bfd_error_bad_value);
b34976b6 599 return FALSE;
252b5132
RH
600 }
601
602 rel->sym_ptr_ptr = sec->symbol_ptr_ptr;
603 }
604
605 rel->addend = 0;
606
607 BFD_ASSERT ((l_rtype & 0xff) < HOWTO_COUNT);
608
609 rel->howto = nlm_powerpc_howto_table + (l_rtype & 0xff);
610
611 BFD_ASSERT (rel->howto->name != NULL
612 && ((l_rtype & 0x8000) != 0
613 ? (rel->howto->complain_on_overflow
614 == complain_overflow_signed)
615 : (rel->howto->complain_on_overflow
616 == complain_overflow_bitfield))
617 && ((l_rtype >> 8) & 0x1f) == rel->howto->bitsize - 1);
618
619 if (l_rsecnm == 0)
620 *secp = code_sec;
621 else if (l_rsecnm == 1)
622 {
623 *secp = data_sec;
eea6121a 624 l_vaddr -= code_sec->size;
252b5132
RH
625 }
626 else
627 {
628 bfd_set_error (bfd_error_bad_value);
b34976b6 629 return FALSE;
252b5132
RH
630 }
631
632 rel->address = l_vaddr;
633
b34976b6 634 return TRUE;
252b5132
RH
635}
636
637#endif /* OLDFORMAT */
638
639/* Mangle PowerPC NLM relocs for output. */
640
b34976b6 641static bfd_boolean
252b5132 642nlm_powerpc_mangle_relocs (abfd, sec, data, offset, count)
5f771d47
ILT
643 bfd *abfd ATTRIBUTE_UNUSED;
644 asection *sec ATTRIBUTE_UNUSED;
0f867abe 645 const PTR data ATTRIBUTE_UNUSED;
5f771d47
ILT
646 bfd_vma offset ATTRIBUTE_UNUSED;
647 bfd_size_type count ATTRIBUTE_UNUSED;
252b5132 648{
b34976b6 649 return TRUE;
252b5132
RH
650}
651
652/* Read a PowerPC NLM import record */
653
b34976b6 654static bfd_boolean
252b5132
RH
655nlm_powerpc_read_import (abfd, sym)
656 bfd *abfd;
657 nlmNAME(symbol_type) *sym;
658{
659 struct nlm_relent *nlm_relocs; /* relocation records for symbol */
660 bfd_size_type rcount; /* number of relocs */
661 bfd_byte temp[NLM_TARGET_LONG_SIZE]; /* temporary 32-bit value */
662 unsigned char symlength; /* length of symbol name */
663 char *name;
664
dc810e39 665 if (bfd_bread ((PTR) &symlength, (bfd_size_type) sizeof (symlength), abfd)
252b5132 666 != sizeof (symlength))
b34976b6 667 return FALSE;
252b5132 668 sym -> symbol.the_bfd = abfd;
dc810e39 669 name = bfd_alloc (abfd, (bfd_size_type) symlength + 1);
252b5132 670 if (name == NULL)
b34976b6 671 return FALSE;
dc810e39 672 if (bfd_bread (name, (bfd_size_type) symlength, abfd) != symlength)
b34976b6 673 return FALSE;
252b5132
RH
674 name[symlength] = '\0';
675 sym -> symbol.name = name;
676 sym -> symbol.flags = 0;
677 sym -> symbol.value = 0;
678 sym -> symbol.section = bfd_und_section_ptr;
dc810e39
AM
679 if (bfd_bread ((PTR) temp, (bfd_size_type) sizeof (temp), abfd)
680 != sizeof (temp))
b34976b6 681 return FALSE;
dc810e39 682 rcount = H_GET_32 (abfd, temp);
252b5132
RH
683 nlm_relocs = ((struct nlm_relent *)
684 bfd_alloc (abfd, rcount * sizeof (struct nlm_relent)));
685 if (nlm_relocs == (struct nlm_relent *) NULL)
b34976b6 686 return FALSE;
252b5132
RH
687 sym -> relocs = nlm_relocs;
688 sym -> rcnt = 0;
689 while (sym -> rcnt < rcount)
690 {
691 asection *section;
1518639e 692
82e51918 693 if (! nlm_powerpc_read_reloc (abfd, sym, &section, &nlm_relocs -> reloc))
b34976b6 694 return FALSE;
252b5132
RH
695 nlm_relocs -> section = section;
696 nlm_relocs++;
697 sym -> rcnt++;
698 }
b34976b6 699 return TRUE;
252b5132
RH
700}
701
702#ifndef OLDFORMAT
703
704/* Write a PowerPC NLM reloc. */
705
b34976b6 706static bfd_boolean
252b5132
RH
707nlm_powerpc_write_import (abfd, sec, rel)
708 bfd *abfd;
709 asection *sec;
710 arelent *rel;
711{
712 asymbol *sym;
713 bfd_vma val;
714 bfd_byte temp[4];
715
716 /* PowerPC NetWare only supports one kind of reloc. */
717 if (rel->addend != 0
718 || rel->howto == NULL
719 || rel->howto->rightshift != 0
720 || rel->howto->size != 2
721 || rel->howto->bitsize != 32
722 || rel->howto->bitpos != 0
723 || rel->howto->pc_relative
724 || (rel->howto->src_mask != 0xffffffff && rel->addend != 0)
725 || rel->howto->dst_mask != 0xffffffff)
726 {
727 bfd_set_error (bfd_error_invalid_operation);
b34976b6 728 return FALSE;
252b5132
RH
729 }
730
731 sym = *rel->sym_ptr_ptr;
732
733 /* The value we write out is the offset into the appropriate
734 segment, rightshifted by two. This offset is the section vma,
735 adjusted by the vma of the lowest section in that segment, plus
736 the address of the relocation. */
737 val = bfd_get_section_vma (abfd, sec) + rel->address;
738 if ((val & 3) != 0)
739 {
740 bfd_set_error (bfd_error_bad_value);
b34976b6 741 return FALSE;
252b5132
RH
742 }
743 val >>= 2;
744
745 /* The high bit is 0 if the reloc is in the data section, or 1 if
746 the reloc is in the code section. */
747 if (bfd_get_section_flags (abfd, sec) & SEC_DATA)
748 val -= nlm_get_data_low (abfd);
749 else
750 {
751 val -= nlm_get_text_low (abfd);
752 val |= NLM_HIBIT;
753 }
1518639e 754
252b5132
RH
755 if (! bfd_is_und_section (bfd_get_section (sym)))
756 {
757 /* This is an internal relocation fixup. The second most
758 significant bit is 0 if this is a reloc against the data
759 segment, or 1 if it is a reloc against the text segment. */
760 if (bfd_get_section_flags (abfd, bfd_get_section (sym)) & SEC_CODE)
761 val |= NLM_HIBIT >> 1;
762 }
763
764 bfd_put_32 (abfd, val, temp);
dc810e39 765 if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp))
b34976b6 766 return FALSE;
252b5132 767
b34976b6 768 return TRUE;
252b5132
RH
769}
770
771#else /* OLDFORMAT */
772
773/* This is used for the reloc handling in the old format. */
774
775/* Write a PowerPC NLM reloc. */
776
b34976b6 777static bfd_boolean
252b5132
RH
778nlm_powerpc_write_reloc (abfd, sec, rel, indx)
779 bfd *abfd;
780 asection *sec;
781 arelent *rel;
782 int indx;
783{
784 struct nlm32_powerpc_external_reloc ext;
785 asection *code_sec, *data_sec, *bss_sec;
786 asymbol *sym;
787 asection *symsec;
788 unsigned long l_symndx;
789 int l_rtype;
790 int l_rsecnm;
791 reloc_howto_type *howto;
792 bfd_size_type address;
793
794 /* Get the sections now, for convenience. */
795 code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
796 data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
797 bss_sec = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
798
799 sym = *rel->sym_ptr_ptr;
800 symsec = bfd_get_section (sym);
801 if (indx != -1)
802 {
803 BFD_ASSERT (bfd_is_und_section (symsec));
804 l_symndx = indx + 3;
805 }
806 else
807 {
808 if (symsec == code_sec)
809 l_symndx = 0;
810 else if (symsec == data_sec)
811 l_symndx = 1;
812 else if (symsec == bss_sec)
813 l_symndx = 2;
814 else
815 {
816 bfd_set_error (bfd_error_bad_value);
b34976b6 817 return FALSE;
252b5132
RH
818 }
819 }
820
dc810e39 821 H_PUT_32 (abfd, l_symndx, ext.l_symndx);
252b5132
RH
822
823 for (howto = nlm_powerpc_howto_table;
824 howto < nlm_powerpc_howto_table + HOWTO_COUNT;
825 howto++)
826 {
827 if (howto->rightshift == rel->howto->rightshift
828 && howto->size == rel->howto->size
829 && howto->bitsize == rel->howto->bitsize
830 && howto->pc_relative == rel->howto->pc_relative
831 && howto->bitpos == rel->howto->bitpos
832 && (howto->partial_inplace == rel->howto->partial_inplace
833 || (! rel->howto->partial_inplace
834 && rel->addend == 0))
835 && (howto->src_mask == rel->howto->src_mask
836 || (rel->howto->src_mask == 0
837 && rel->addend == 0))
838 && howto->dst_mask == rel->howto->dst_mask
839 && howto->pcrel_offset == rel->howto->pcrel_offset)
840 break;
841 }
842 if (howto >= nlm_powerpc_howto_table + HOWTO_COUNT)
843 {
844 bfd_set_error (bfd_error_bad_value);
b34976b6 845 return FALSE;
252b5132
RH
846 }
847
848 l_rtype = howto->type;
849 if (howto->complain_on_overflow == complain_overflow_signed)
850 l_rtype |= 0x8000;
851 l_rtype |= (howto->bitsize - 1) << 8;
dc810e39 852 H_PUT_16 (abfd, l_rtype, ext.l_rtype);
252b5132
RH
853
854 address = rel->address;
855
856 if (sec == code_sec)
857 l_rsecnm = 0;
858 else if (sec == data_sec)
859 {
860 l_rsecnm = 1;
eea6121a 861 address += code_sec->size;
252b5132
RH
862 }
863 else
864 {
865 bfd_set_error (bfd_error_bad_value);
b34976b6 866 return FALSE;
252b5132
RH
867 }
868
dc810e39
AM
869 H_PUT_16 (abfd, l_rsecnm, ext.l_rsecnm);
870 H_PUT_32 (abfd, address, ext.l_vaddr);
252b5132 871
dc810e39 872 if (bfd_bwrite (&ext, (bfd_size_type) sizeof ext, abfd) != sizeof ext)
b34976b6 873 return FALSE;
252b5132 874
b34976b6 875 return TRUE;
252b5132
RH
876}
877
878/* Write a PowerPC NLM import. */
879
b34976b6 880static bfd_boolean
252b5132
RH
881nlm_powerpc_write_import (abfd, sec, rel)
882 bfd *abfd;
883 asection *sec;
884 arelent *rel;
885{
886 return nlm_powerpc_write_reloc (abfd, sec, rel, -1);
887}
888
889#endif /* OLDFORMAT */
890
891/* Write a PowerPC NLM external symbol. This routine keeps a static
892 count of the symbol index. FIXME: I don't know if this is
893 necessary, and the index never gets reset. */
894
b34976b6 895static bfd_boolean
252b5132
RH
896nlm_powerpc_write_external (abfd, count, sym, relocs)
897 bfd *abfd;
898 bfd_size_type count;
899 asymbol *sym;
900 struct reloc_and_sec *relocs;
901{
902 unsigned int i;
903 bfd_byte len;
904 unsigned char temp[NLM_TARGET_LONG_SIZE];
905#ifdef OLDFORMAT
906 static int indx;
907#endif
908
909 len = strlen (sym->name);
dc810e39
AM
910 if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd)
911 != sizeof (bfd_byte))
912 || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
b34976b6 913 return FALSE;
252b5132
RH
914
915 bfd_put_32 (abfd, count, temp);
dc810e39 916 if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp))
b34976b6 917 return FALSE;
252b5132
RH
918
919 for (i = 0; i < count; i++)
920 {
921#ifndef OLDFORMAT
922 if (! nlm_powerpc_write_import (abfd, relocs[i].sec, relocs[i].rel))
b34976b6 923 return FALSE;
252b5132
RH
924#else
925 if (! nlm_powerpc_write_reloc (abfd, relocs[i].sec,
926 relocs[i].rel, indx))
b34976b6 927 return FALSE;
252b5132
RH
928#endif
929 }
930
931#ifdef OLDFORMAT
932 ++indx;
933#endif
934
b34976b6 935 return TRUE;
252b5132
RH
936}
937\f
938#ifndef OLDFORMAT
939
940/* PowerPC Netware uses a word offset, not a byte offset, for public
941 symbols. */
942
943/* Set the section for a public symbol. */
944
b34976b6 945static bfd_boolean
252b5132
RH
946nlm_powerpc_set_public_section (abfd, sym)
947 bfd *abfd;
948 nlmNAME(symbol_type) *sym;
949{
950 if (sym->symbol.value & NLM_HIBIT)
951 {
952 sym->symbol.value &= ~NLM_HIBIT;
953 sym->symbol.flags |= BSF_FUNCTION;
954 sym->symbol.section =
955 bfd_get_section_by_name (abfd, NLM_CODE_NAME);
956 }
957 else
958 {
959 sym->symbol.section =
960 bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
961 }
962
963 sym->symbol.value <<= 2;
964
b34976b6 965 return TRUE;
252b5132
RH
966}
967
968/* Get the offset to write out for a public symbol. */
969
970static bfd_vma
971nlm_powerpc_get_public_offset (abfd, sym)
972 bfd *abfd;
973 asymbol *sym;
974{
975 bfd_vma offset;
976 asection *sec;
977
978 offset = bfd_asymbol_value (sym);
979 sec = bfd_get_section (sym);
980 if (sec->flags & SEC_CODE)
981 {
982 offset -= nlm_get_text_low (abfd);
983 offset |= NLM_HIBIT;
984 }
985 else if (sec->flags & (SEC_DATA | SEC_ALLOC))
986 {
987 /* SEC_ALLOC is for the .bss section. */
988 offset -= nlm_get_data_low (abfd);
989 }
990 else
991 {
992 /* We can't handle an exported symbol that is not in the code or
993 data segment. */
994 bfd_set_error (bfd_error_invalid_operation);
995 /* FIXME: No way to return error. */
996 abort ();
997 }
998
999 return offset;
1000}
1001
1002#endif /* ! defined (OLDFORMAT) */
1003\f
1004#include "nlmswap.h"
1005
1006static const struct nlm_backend_data nlm32_powerpc_backend =
1007{
1008 "NetWare PowerPC Module \032",
1009 sizeof (Nlm32_powerpc_External_Fixed_Header),
1010#ifndef OLDFORMAT
1011 0, /* optional_prefix_size */
1012#else
1013 sizeof (struct nlm32_powerpc_external_prefix_header),
1014#endif
1015 bfd_arch_powerpc,
1016 0,
b34976b6 1017 FALSE,
252b5132
RH
1018#ifndef OLDFORMAT
1019 0, /* backend_object_p */
1020 0, /* write_prefix */
1021#else
1022 nlm_powerpc_backend_object_p,
1023 nlm_powerpc_write_prefix,
1024#endif
1025 nlm_powerpc_read_reloc,
1026 nlm_powerpc_mangle_relocs,
1027 nlm_powerpc_read_import,
1028 nlm_powerpc_write_import,
1029#ifndef OLDFORMAT
1030 nlm_powerpc_set_public_section,
1031 nlm_powerpc_get_public_offset,
1032#else
1033 0, /* set_public_section */
1034 0, /* get_public_offset */
1035#endif
1036 nlm_swap_fixed_header_in,
1037 nlm_swap_fixed_header_out,
1038 nlm_powerpc_write_external,
1039 0, /* write_export */
1040};
1041
1042#define TARGET_BIG_NAME "nlm32-powerpc"
1043#define TARGET_BIG_SYM nlmNAME(powerpc_vec)
1044#define TARGET_BACKEND_DATA &nlm32_powerpc_backend
1045
1046#include "nlm-target.h"
This page took 0.367277 seconds and 4 git commands to generate.