1 /* Support for 32-bit PowerPC NLM (NetWare Loadable Module)
2 Copyright 1994, 1995, 1999, 2000, 2001, 2002, 2003, 2004
3 Free Software Foundation, Inc.
5 This file is part of BFD, the Binary File Descriptor library.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
25 /* The format of a PowerPC NLM changed. Define OLDFORMAT to get the
30 #include "nlm/ppc-ext.h"
31 #define Nlm_External_Fixed_Header Nlm32_powerpc_External_Fixed_Header
36 static bfd_boolean nlm_powerpc_backend_object_p
38 static bfd_boolean nlm_powerpc_write_prefix
42 static bfd_boolean nlm_powerpc_read_reloc
43 PARAMS ((bfd
*, nlmNAME(symbol_type
) *, asection
**, arelent
*));
44 static bfd_boolean nlm_powerpc_mangle_relocs
45 PARAMS ((bfd
*, asection
*, const PTR
, bfd_vma
, bfd_size_type
));
46 static bfd_boolean nlm_powerpc_read_import
47 PARAMS ((bfd
*, nlmNAME(symbol_type
) *));
50 static bfd_boolean nlm_powerpc_write_reloc
51 PARAMS ((bfd
*, asection
*, arelent
*, int));
54 static bfd_boolean nlm_powerpc_write_import
55 PARAMS ((bfd
*, asection
*, arelent
*));
56 static bfd_boolean nlm_powerpc_write_external
57 PARAMS ((bfd
*, bfd_size_type
, asymbol
*, struct reloc_and_sec
*));
60 static bfd_boolean nlm_powerpc_set_public_section
61 PARAMS ((bfd
*, nlmNAME(symbol_type
) *));
62 static bfd_vma nlm_powerpc_get_public_offset
63 PARAMS ((bfd
*, asymbol
*));
68 /* The prefix header is only used in the old format. */
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. */
75 nlm_powerpc_backend_object_p (abfd
)
78 struct nlm32_powerpc_external_prefix_header s
;
80 if (bfd_bread ((PTR
) &s
, (bfd_size_type
) sizeof s
, abfd
) != sizeof s
)
83 if (memcmp (s
.signature
, NLM32_POWERPC_SIGNATURE
, sizeof s
.signature
) != 0
84 || H_GET_32 (abfd
, s
.headerVersion
) != NLM32_POWERPC_HEADER_VERSION
)
90 /* Write out the prefix. */
93 nlm_powerpc_write_prefix (abfd
)
96 struct nlm32_powerpc_external_prefix_header s
;
98 memset (&s
, 0, sizeof s
);
99 memcpy (s
.signature
, NLM32_POWERPC_SIGNATURE
, sizeof s
.signature
);
100 H_PUT_32 (abfd
, NLM32_POWERPC_HEADER_VERSION
, s
.headerVersion
);
101 H_PUT_32 (abfd
, 0, s
.origins
);
103 /* FIXME: What should we do about the date? */
105 if (bfd_bwrite ((PTR
) &s
, (bfd_size_type
) sizeof s
, abfd
) != sizeof s
)
111 #endif /* OLDFORMAT */
115 /* There is only one type of reloc in a PowerPC NLM. */
117 static reloc_howto_type nlm_powerpc_howto
=
120 2, /* size (0 = byte, 1 = short, 2 = long) */
122 FALSE
, /* pc_relative */
124 complain_overflow_bitfield
, /* complain_on_overflow */
125 0, /* special_function */
127 TRUE
, /* partial_inplace */
128 0xffffffff, /* src_mask */
129 0xffffffff, /* dst_mask */
130 FALSE
); /* pcrel_offset */
132 /* Read a PowerPC NLM reloc. */
135 nlm_powerpc_read_reloc (abfd
, sym
, secp
, rel
)
137 nlmNAME(symbol_type
) *sym
;
145 if (bfd_bread (temp
, (bfd_size_type
) sizeof (temp
), abfd
) != sizeof (temp
))
148 val
= bfd_get_32 (abfd
, temp
);
150 /* The value is a word offset into either the code or data segment.
151 This is the location which needs to be adjusted.
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.
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.
162 If this is an imported symbol, the second most significant bit is
163 not used and must be 0. */
165 if ((val
& NLM_HIBIT
) == 0)
166 name
= NLM_INITIALIZED_DATA_NAME
;
169 name
= NLM_CODE_NAME
;
172 *secp
= bfd_get_section_by_name (abfd
, name
);
176 if ((val
& (NLM_HIBIT
>> 1)) == 0)
177 name
= NLM_INITIALIZED_DATA_NAME
;
180 name
= NLM_CODE_NAME
;
181 val
&=~ (NLM_HIBIT
>> 1);
183 rel
->sym_ptr_ptr
= bfd_get_section_by_name (abfd
, name
)->symbol_ptr_ptr
;
186 rel
->howto
= &nlm_powerpc_howto
;
188 rel
->address
= val
<< 2;
194 #else /* OLDFORMAT */
196 /* This reloc handling is only applicable to the old format. */
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. */
201 static reloc_howto_type nlm_powerpc_howto_table
[] =
203 /* Standard 32 bit relocation. */
206 2, /* size (0 = byte, 1 = short, 2 = long) */
208 FALSE
, /* pc_relative */
210 complain_overflow_bitfield
, /* complain_on_overflow */
211 0, /* special_function */
213 TRUE
, /* partial_inplace */
214 0xffffffff, /* src_mask */
215 0xffffffff, /* dst_mask */
216 FALSE
), /* pcrel_offset */
218 /* 32 bit relocation, but store negative value. */
221 -2, /* size (0 = byte, 1 = short, 2 = long) */
223 FALSE
, /* pc_relative */
225 complain_overflow_bitfield
, /* complain_on_overflow */
226 0, /* special_function */
228 TRUE
, /* partial_inplace */
229 0xffffffff, /* src_mask */
230 0xffffffff, /* dst_mask */
231 FALSE
), /* pcrel_offset */
233 /* 32 bit PC relative relocation. */
236 2, /* size (0 = byte, 1 = short, 2 = long) */
238 TRUE
, /* pc_relative */
240 complain_overflow_signed
, /* complain_on_overflow */
241 0, /* special_function */
243 TRUE
, /* partial_inplace */
244 0xffffffff, /* src_mask */
245 0xffffffff, /* dst_mask */
246 FALSE
), /* pcrel_offset */
248 /* 16 bit TOC relative relocation. */
251 1, /* size (0 = byte, 1 = short, 2 = long) */
253 FALSE
, /* pc_relative */
255 complain_overflow_signed
, /* complain_on_overflow */
256 0, /* special_function */
258 TRUE
, /* partial_inplace */
259 0xffff, /* src_mask */
260 0xffff, /* dst_mask */
261 FALSE
), /* pcrel_offset */
263 /* I don't really know what this is. */
266 2, /* size (0 = byte, 1 = short, 2 = long) */
268 FALSE
, /* pc_relative */
270 complain_overflow_bitfield
, /* complain_on_overflow */
271 0, /* special_function */
273 TRUE
, /* partial_inplace */
274 0xffffffff, /* src_mask */
275 0xffffffff, /* dst_mask */
276 FALSE
), /* pcrel_offset */
278 /* External TOC relative symbol. */
281 2, /* size (0 = byte, 1 = short, 2 = long) */
283 FALSE
, /* pc_relative */
285 complain_overflow_bitfield
, /* complain_on_overflow */
286 0, /* special_function */
288 TRUE
, /* partial_inplace */
289 0xffff, /* src_mask */
290 0xffff, /* dst_mask */
291 FALSE
), /* pcrel_offset */
293 /* Local TOC relative symbol. */
296 2, /* size (0 = byte, 1 = short, 2 = long) */
298 FALSE
, /* pc_relative */
300 complain_overflow_bitfield
, /* complain_on_overflow */
301 0, /* special_function */
303 TRUE
, /* partial_inplace */
304 0xffff, /* src_mask */
305 0xffff, /* dst_mask */
306 FALSE
), /* pcrel_offset */
310 /* Non modifiable absolute branch. */
313 2, /* size (0 = byte, 1 = short, 2 = long) */
315 FALSE
, /* pc_relative */
317 complain_overflow_bitfield
, /* complain_on_overflow */
318 0, /* special_function */
320 TRUE
, /* partial_inplace */
321 0x3fffffc, /* src_mask */
322 0x3fffffc, /* dst_mask */
323 FALSE
), /* pcrel_offset */
327 /* Non modifiable relative branch. */
328 HOWTO (0xa, /* type */
330 2, /* size (0 = byte, 1 = short, 2 = long) */
332 TRUE
, /* pc_relative */
334 complain_overflow_signed
, /* complain_on_overflow */
335 0, /* special_function */
337 TRUE
, /* partial_inplace */
338 0x3fffffc, /* src_mask */
339 0x3fffffc, /* dst_mask */
340 FALSE
), /* pcrel_offset */
345 HOWTO (0xc, /* type */
347 2, /* size (0 = byte, 1 = short, 2 = long) */
349 FALSE
, /* pc_relative */
351 complain_overflow_bitfield
, /* complain_on_overflow */
352 0, /* special_function */
354 TRUE
, /* partial_inplace */
355 0xffff, /* src_mask */
356 0xffff, /* dst_mask */
357 FALSE
), /* pcrel_offset */
360 HOWTO (0xd, /* type */
362 2, /* size (0 = byte, 1 = short, 2 = long) */
364 FALSE
, /* pc_relative */
366 complain_overflow_bitfield
, /* complain_on_overflow */
367 0, /* special_function */
369 TRUE
, /* partial_inplace */
370 0xffff, /* src_mask */
371 0xffff, /* dst_mask */
372 FALSE
), /* pcrel_offset */
376 /* Non-relocating reference. */
377 HOWTO (0xf, /* type */
379 2, /* size (0 = byte, 1 = short, 2 = long) */
381 FALSE
, /* pc_relative */
383 complain_overflow_bitfield
, /* complain_on_overflow */
384 0, /* special_function */
386 FALSE
, /* partial_inplace */
389 FALSE
), /* pcrel_offset */
394 /* TOC relative indirect load. */
395 HOWTO (0x12, /* type */
397 2, /* size (0 = byte, 1 = short, 2 = long) */
399 FALSE
, /* pc_relative */
401 complain_overflow_bitfield
, /* complain_on_overflow */
402 0, /* special_function */
404 TRUE
, /* partial_inplace */
405 0xffff, /* src_mask */
406 0xffff, /* dst_mask */
407 FALSE
), /* pcrel_offset */
409 /* TOC relative load address. */
410 HOWTO (0x13, /* type */
412 2, /* size (0 = byte, 1 = short, 2 = long) */
414 FALSE
, /* pc_relative */
416 complain_overflow_bitfield
, /* complain_on_overflow */
417 0, /* special_function */
419 TRUE
, /* partial_inplace */
420 0xffff, /* src_mask */
421 0xffff, /* dst_mask */
422 FALSE
), /* pcrel_offset */
424 /* Modifiable relative branch. */
425 HOWTO (0x14, /* type */
427 2, /* size (0 = byte, 1 = short, 2 = long) */
429 FALSE
, /* pc_relative */
431 complain_overflow_bitfield
, /* complain_on_overflow */
432 0, /* special_function */
433 "R_RRTBI", /* name */
434 TRUE
, /* partial_inplace */
435 0xffffffff, /* src_mask */
436 0xffffffff, /* dst_mask */
437 FALSE
), /* pcrel_offset */
439 /* Modifiable absolute branch. */
440 HOWTO (0x15, /* type */
442 2, /* size (0 = byte, 1 = short, 2 = long) */
444 FALSE
, /* pc_relative */
446 complain_overflow_bitfield
, /* complain_on_overflow */
447 0, /* special_function */
448 "R_RRTBA", /* name */
449 TRUE
, /* partial_inplace */
450 0xffffffff, /* src_mask */
451 0xffffffff, /* dst_mask */
452 FALSE
), /* pcrel_offset */
454 /* Modifiable call absolute indirect. */
455 HOWTO (0x16, /* type */
457 2, /* size (0 = byte, 1 = short, 2 = long) */
459 FALSE
, /* pc_relative */
461 complain_overflow_bitfield
, /* complain_on_overflow */
462 0, /* special_function */
464 TRUE
, /* partial_inplace */
465 0xffff, /* src_mask */
466 0xffff, /* dst_mask */
467 FALSE
), /* pcrel_offset */
469 /* Modifiable call relative. */
470 HOWTO (0x17, /* type */
472 2, /* size (0 = byte, 1 = short, 2 = long) */
474 FALSE
, /* pc_relative */
476 complain_overflow_bitfield
, /* complain_on_overflow */
477 0, /* special_function */
479 TRUE
, /* partial_inplace */
480 0xffff, /* src_mask */
481 0xffff, /* dst_mask */
482 FALSE
), /* pcrel_offset */
484 /* Modifiable branch absolute. */
485 HOWTO (0x18, /* type */
487 2, /* size (0 = byte, 1 = short, 2 = long) */
489 FALSE
, /* pc_relative */
491 complain_overflow_bitfield
, /* complain_on_overflow */
492 0, /* special_function */
494 TRUE
, /* partial_inplace */
495 0xffff, /* src_mask */
496 0xffff, /* dst_mask */
497 FALSE
), /* pcrel_offset */
499 /* Modifiable branch absolute. */
500 HOWTO (0x19, /* type */
502 2, /* size (0 = byte, 1 = short, 2 = long) */
504 FALSE
, /* pc_relative */
506 complain_overflow_bitfield
, /* complain_on_overflow */
507 0, /* special_function */
509 TRUE
, /* partial_inplace */
510 0xffff, /* src_mask */
511 0xffff, /* dst_mask */
512 FALSE
), /* pcrel_offset */
514 /* Modifiable branch relative. */
515 HOWTO (0x1a, /* type */
517 2, /* size (0 = byte, 1 = short, 2 = long) */
519 FALSE
, /* pc_relative */
521 complain_overflow_signed
, /* complain_on_overflow */
522 0, /* special_function */
524 TRUE
, /* partial_inplace */
525 0xffff, /* src_mask */
526 0xffff, /* dst_mask */
527 FALSE
), /* pcrel_offset */
529 /* Modifiable branch absolute. */
530 HOWTO (0x1b, /* type */
532 2, /* size (0 = byte, 1 = short, 2 = long) */
534 FALSE
, /* pc_relative */
536 complain_overflow_bitfield
, /* complain_on_overflow */
537 0, /* special_function */
539 TRUE
, /* partial_inplace */
540 0xffff, /* src_mask */
541 0xffff, /* dst_mask */
542 FALSE
) /* pcrel_offset */
545 #define HOWTO_COUNT (sizeof nlm_powerpc_howto_table \
546 / sizeof nlm_powerpc_howto_table[0])
548 /* Read a PowerPC NLM reloc. */
551 nlm_powerpc_read_reloc (abfd
, sym
, secp
, rel
)
553 nlmNAME(symbol_type
) *sym
;
557 struct nlm32_powerpc_external_reloc ext
;
559 unsigned long l_symndx
;
562 asection
*code_sec
, *data_sec
, *bss_sec
;
564 /* Read the reloc from the file. */
565 if (bfd_bread (&ext
, (bfd_size_type
) sizeof ext
, abfd
) != sizeof ext
)
568 /* Swap in the fields. */
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
);
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
);
579 /* Work out the arelent fields. */
582 /* This is an import. sym_ptr_ptr is filled in by
583 nlm_canonicalize_reloc. */
584 rel
->sym_ptr_ptr
= NULL
;
592 else if (l_symndx
== 1)
594 else if (l_symndx
== 2)
598 bfd_set_error (bfd_error_bad_value
);
602 rel
->sym_ptr_ptr
= sec
->symbol_ptr_ptr
;
607 BFD_ASSERT ((l_rtype
& 0xff) < HOWTO_COUNT
);
609 rel
->howto
= nlm_powerpc_howto_table
+ (l_rtype
& 0xff);
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);
621 else if (l_rsecnm
== 1)
624 l_vaddr
-= code_sec
->size
;
628 bfd_set_error (bfd_error_bad_value
);
632 rel
->address
= l_vaddr
;
637 #endif /* OLDFORMAT */
639 /* Mangle PowerPC NLM relocs for output. */
642 nlm_powerpc_mangle_relocs (abfd
, sec
, data
, offset
, count
)
643 bfd
*abfd ATTRIBUTE_UNUSED
;
644 asection
*sec ATTRIBUTE_UNUSED
;
645 const PTR data ATTRIBUTE_UNUSED
;
646 bfd_vma offset ATTRIBUTE_UNUSED
;
647 bfd_size_type count ATTRIBUTE_UNUSED
;
652 /* Read a PowerPC NLM import record */
655 nlm_powerpc_read_import (abfd
, sym
)
657 nlmNAME(symbol_type
) *sym
;
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 */
665 if (bfd_bread ((PTR
) &symlength
, (bfd_size_type
) sizeof (symlength
), abfd
)
666 != sizeof (symlength
))
668 sym
-> symbol
.the_bfd
= abfd
;
669 name
= bfd_alloc (abfd
, (bfd_size_type
) symlength
+ 1);
672 if (bfd_bread (name
, (bfd_size_type
) symlength
, abfd
) != symlength
)
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
;
679 if (bfd_bread ((PTR
) temp
, (bfd_size_type
) sizeof (temp
), abfd
)
682 rcount
= H_GET_32 (abfd
, temp
);
683 nlm_relocs
= ((struct nlm_relent
*)
684 bfd_alloc (abfd
, rcount
* sizeof (struct nlm_relent
)));
685 if (nlm_relocs
== (struct nlm_relent
*) NULL
)
687 sym
-> relocs
= nlm_relocs
;
689 while (sym
-> rcnt
< rcount
)
693 if (! nlm_powerpc_read_reloc (abfd
, sym
, §ion
, &nlm_relocs
-> reloc
))
695 nlm_relocs
-> section
= section
;
704 /* Write a PowerPC NLM reloc. */
707 nlm_powerpc_write_import (abfd
, sec
, rel
)
716 /* PowerPC NetWare only supports one kind of reloc. */
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)
727 bfd_set_error (bfd_error_invalid_operation
);
731 sym
= *rel
->sym_ptr_ptr
;
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
;
740 bfd_set_error (bfd_error_bad_value
);
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
);
751 val
-= nlm_get_text_low (abfd
);
755 if (! bfd_is_und_section (bfd_get_section (sym
)))
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;
764 bfd_put_32 (abfd
, val
, temp
);
765 if (bfd_bwrite (temp
, (bfd_size_type
) sizeof (temp
), abfd
) != sizeof (temp
))
771 #else /* OLDFORMAT */
773 /* This is used for the reloc handling in the old format. */
775 /* Write a PowerPC NLM reloc. */
778 nlm_powerpc_write_reloc (abfd
, sec
, rel
, indx
)
784 struct nlm32_powerpc_external_reloc ext
;
785 asection
*code_sec
, *data_sec
, *bss_sec
;
788 unsigned long l_symndx
;
791 reloc_howto_type
*howto
;
792 bfd_size_type address
;
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
);
799 sym
= *rel
->sym_ptr_ptr
;
800 symsec
= bfd_get_section (sym
);
803 BFD_ASSERT (bfd_is_und_section (symsec
));
808 if (symsec
== code_sec
)
810 else if (symsec
== data_sec
)
812 else if (symsec
== bss_sec
)
816 bfd_set_error (bfd_error_bad_value
);
821 H_PUT_32 (abfd
, l_symndx
, ext
.l_symndx
);
823 for (howto
= nlm_powerpc_howto_table
;
824 howto
< nlm_powerpc_howto_table
+ HOWTO_COUNT
;
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
)
842 if (howto
>= nlm_powerpc_howto_table
+ HOWTO_COUNT
)
844 bfd_set_error (bfd_error_bad_value
);
848 l_rtype
= howto
->type
;
849 if (howto
->complain_on_overflow
== complain_overflow_signed
)
851 l_rtype
|= (howto
->bitsize
- 1) << 8;
852 H_PUT_16 (abfd
, l_rtype
, ext
.l_rtype
);
854 address
= rel
->address
;
858 else if (sec
== data_sec
)
861 address
+= code_sec
->size
;
865 bfd_set_error (bfd_error_bad_value
);
869 H_PUT_16 (abfd
, l_rsecnm
, ext
.l_rsecnm
);
870 H_PUT_32 (abfd
, address
, ext
.l_vaddr
);
872 if (bfd_bwrite (&ext
, (bfd_size_type
) sizeof ext
, abfd
) != sizeof ext
)
878 /* Write a PowerPC NLM import. */
881 nlm_powerpc_write_import (abfd
, sec
, rel
)
886 return nlm_powerpc_write_reloc (abfd
, sec
, rel
, -1);
889 #endif /* OLDFORMAT */
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. */
896 nlm_powerpc_write_external (abfd
, count
, sym
, relocs
)
900 struct reloc_and_sec
*relocs
;
904 unsigned char temp
[NLM_TARGET_LONG_SIZE
];
909 len
= strlen (sym
->name
);
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
)
915 bfd_put_32 (abfd
, count
, temp
);
916 if (bfd_bwrite (temp
, (bfd_size_type
) sizeof (temp
), abfd
) != sizeof (temp
))
919 for (i
= 0; i
< count
; i
++)
922 if (! nlm_powerpc_write_import (abfd
, relocs
[i
].sec
, relocs
[i
].rel
))
925 if (! nlm_powerpc_write_reloc (abfd
, relocs
[i
].sec
,
926 relocs
[i
].rel
, indx
))
940 /* PowerPC Netware uses a word offset, not a byte offset, for public
943 /* Set the section for a public symbol. */
946 nlm_powerpc_set_public_section (abfd
, sym
)
948 nlmNAME(symbol_type
) *sym
;
950 if (sym
->symbol
.value
& NLM_HIBIT
)
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
);
959 sym
->symbol
.section
=
960 bfd_get_section_by_name (abfd
, NLM_INITIALIZED_DATA_NAME
);
963 sym
->symbol
.value
<<= 2;
968 /* Get the offset to write out for a public symbol. */
971 nlm_powerpc_get_public_offset (abfd
, sym
)
978 offset
= bfd_asymbol_value (sym
);
979 sec
= bfd_get_section (sym
);
980 if (sec
->flags
& SEC_CODE
)
982 offset
-= nlm_get_text_low (abfd
);
985 else if (sec
->flags
& (SEC_DATA
| SEC_ALLOC
))
987 /* SEC_ALLOC is for the .bss section. */
988 offset
-= nlm_get_data_low (abfd
);
992 /* We can't handle an exported symbol that is not in the code or
994 bfd_set_error (bfd_error_invalid_operation
);
995 /* FIXME: No way to return error. */
1002 #endif /* ! defined (OLDFORMAT) */
1004 #include "nlmswap.h"
1006 static const struct nlm_backend_data nlm32_powerpc_backend
=
1008 "NetWare PowerPC Module \032",
1009 sizeof (Nlm32_powerpc_External_Fixed_Header
),
1011 0, /* optional_prefix_size */
1013 sizeof (struct nlm32_powerpc_external_prefix_header
),
1019 0, /* backend_object_p */
1020 0, /* write_prefix */
1022 nlm_powerpc_backend_object_p
,
1023 nlm_powerpc_write_prefix
,
1025 nlm_powerpc_read_reloc
,
1026 nlm_powerpc_mangle_relocs
,
1027 nlm_powerpc_read_import
,
1028 nlm_powerpc_write_import
,
1030 nlm_powerpc_set_public_section
,
1031 nlm_powerpc_get_public_offset
,
1033 0, /* set_public_section */
1034 0, /* get_public_offset */
1036 nlm_swap_fixed_header_in
,
1037 nlm_swap_fixed_header_out
,
1038 nlm_powerpc_write_external
,
1039 0, /* write_export */
1042 #define TARGET_BIG_NAME "nlm32-powerpc"
1043 #define TARGET_BIG_SYM nlmNAME(powerpc_vec)
1044 #define TARGET_BACKEND_DATA &nlm32_powerpc_backend
1046 #include "nlm-target.h"