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