1 /* Support for 32-bit PowerPC NLM (NetWare Loadable Module)
2 Copyright (C) 1994-2017 Free Software Foundation, Inc.
4 This file is part of BFD, the Binary File Descriptor library.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, 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
37 /* The prefix header is only used in the old format. */
39 /* PowerPC NLM's have a prefix header before the standard NLM. This
40 function reads it in, verifies the version, and seeks the bfd to
41 the location before the regular NLM header. */
44 nlm_powerpc_backend_object_p (bfd
*abfd
)
46 struct nlm32_powerpc_external_prefix_header s
;
48 if (bfd_bread (& s
, (bfd_size_type
) sizeof s
, abfd
) != sizeof s
)
51 if (memcmp (s
.signature
, NLM32_POWERPC_SIGNATURE
, sizeof s
.signature
) != 0
52 || H_GET_32 (abfd
, s
.headerVersion
) != NLM32_POWERPC_HEADER_VERSION
)
58 /* Write out the prefix. */
61 nlm_powerpc_write_prefix (bfd
*abfd
)
63 struct nlm32_powerpc_external_prefix_header s
;
65 memset (&s
, 0, sizeof s
);
66 memcpy (s
.signature
, NLM32_POWERPC_SIGNATURE
, sizeof s
.signature
);
67 H_PUT_32 (abfd
, NLM32_POWERPC_HEADER_VERSION
, s
.headerVersion
);
68 H_PUT_32 (abfd
, 0, s
.origins
);
70 /* FIXME: What should we do about the date? */
72 if (bfd_bwrite (& s
, (bfd_size_type
) sizeof s
, abfd
) != sizeof s
)
78 /* This reloc handling is only applicable to the old format. */
80 /* How to process the various reloc types. PowerPC NLMs use XCOFF
81 reloc types, and I have just copied the XCOFF reloc table here. */
83 static reloc_howto_type nlm_powerpc_howto_table
[] =
85 /* Standard 32 bit relocation. */
88 2, /* Size (0 = byte, 1 = short, 2 = long). */
90 FALSE
, /* PC relative. */
92 complain_overflow_bitfield
, /* Complain_on_overflow. */
93 0, /* Special_function. */
95 TRUE
, /* Partial_inplace. */
96 0xffffffff, /* Source mask. */
97 0xffffffff, /* Dest mask. */
98 FALSE
), /* PC rel offset. */
100 /* 32 bit relocation, but store negative value. */
101 HOWTO (1, /* Type. */
103 -2, /* Size (0 = byte, 1 = short, 2 = long). */
105 FALSE
, /* PC relative. */
107 complain_overflow_bitfield
, /* Complain_on_overflow. */
108 0, /* Special_function. */
110 TRUE
, /* Partial_inplace. */
111 0xffffffff, /* Source mask. */
112 0xffffffff, /* Dest mask. */
113 FALSE
), /* PC rel offset. */
115 /* 32 bit PC relative relocation. */
116 HOWTO (2, /* Type. */
118 2, /* Size (0 = byte, 1 = short, 2 = long). */
120 TRUE
, /* PC relative. */
122 complain_overflow_signed
, /* Complain_on_overflow. */
123 0, /* Special_function. */
125 TRUE
, /* Partial_inplace. */
126 0xffffffff, /* Source mask. */
127 0xffffffff, /* Dest mask. */
128 FALSE
), /* PC rel offset. */
130 /* 16 bit TOC relative relocation. */
131 HOWTO (3, /* Type. */
133 1, /* Size (0 = byte, 1 = short, 2 = long). */
135 FALSE
, /* PC relative. */
137 complain_overflow_signed
, /* Complain_on_overflow. */
138 0, /* Special_function. */
140 TRUE
, /* Partial_inplace. */
141 0xffff, /* Source mask. */
142 0xffff, /* Dest mask. */
143 FALSE
), /* PC rel offset. */
145 /* I don't really know what this is. */
146 HOWTO (4, /* Type. */
148 2, /* Size (0 = byte, 1 = short, 2 = long). */
150 FALSE
, /* PC relative. */
152 complain_overflow_bitfield
, /* Complain_on_overflow. */
153 0, /* Special_function. */
155 TRUE
, /* Partial_inplace. */
156 0xffffffff, /* Source mask. */
157 0xffffffff, /* Dest mask. */
158 FALSE
), /* PC rel offset. */
160 /* External TOC relative symbol. */
161 HOWTO (5, /* Type. */
163 2, /* Size (0 = byte, 1 = short, 2 = long). */
165 FALSE
, /* PC relative. */
167 complain_overflow_bitfield
, /* Complain_on_overflow. */
168 0, /* Special_function. */
170 TRUE
, /* Partial_inplace. */
171 0xffff, /* Source mask. */
172 0xffff, /* Dest mask. */
173 FALSE
), /* PC rel offset. */
175 /* Local TOC relative symbol. */
176 HOWTO (6, /* Type. */
178 2, /* Size (0 = byte, 1 = short, 2 = long). */
180 FALSE
, /* PC relative. */
182 complain_overflow_bitfield
, /* Complain_on_overflow. */
183 0, /* Special_function. */
185 TRUE
, /* Partial_inplace. */
186 0xffff, /* Source mask. */
187 0xffff, /* Dest mask. */
188 FALSE
), /* PC rel offset. */
192 /* Non modifiable absolute branch. */
193 HOWTO (8, /* Type. */
195 2, /* Size (0 = byte, 1 = short, 2 = long). */
197 FALSE
, /* PC relative. */
199 complain_overflow_bitfield
, /* Complain_on_overflow. */
200 0, /* Special_function. */
202 TRUE
, /* Partial_inplace. */
203 0x3fffffc, /* Source mask. */
204 0x3fffffc, /* Dest mask. */
205 FALSE
), /* PC rel offset. */
209 /* Non modifiable relative branch. */
210 HOWTO (0xa, /* Type. */
212 2, /* Size (0 = byte, 1 = short, 2 = long). */
214 TRUE
, /* PC relative. */
216 complain_overflow_signed
, /* Complain_on_overflow. */
217 0, /* Special_function. */
219 TRUE
, /* Partial_inplace. */
220 0x3fffffc, /* Source mask. */
221 0x3fffffc, /* Dest mask. */
222 FALSE
), /* PC rel offset. */
227 HOWTO (0xc, /* Type. */
229 2, /* Size (0 = byte, 1 = short, 2 = long). */
231 FALSE
, /* PC relative. */
233 complain_overflow_bitfield
, /* Complain_on_overflow. */
234 0, /* Special_function. */
236 TRUE
, /* Partial_inplace. */
237 0xffff, /* Source mask. */
238 0xffff, /* Dest mask. */
239 FALSE
), /* PC rel offset. */
242 HOWTO (0xd, /* Type. */
244 2, /* Size (0 = byte, 1 = short, 2 = long). */
246 FALSE
, /* PC relative. */
248 complain_overflow_bitfield
, /* Complain_on_overflow. */
249 0, /* Special_function. */
251 TRUE
, /* Partial_inplace. */
252 0xffff, /* Source mask. */
253 0xffff, /* Dest mask. */
254 FALSE
), /* PC rel offset. */
258 /* Non-relocating reference. */
259 HOWTO (0xf, /* Type. */
261 2, /* Size (0 = byte, 1 = short, 2 = long). */
263 FALSE
, /* PC relative. */
265 complain_overflow_bitfield
, /* Complain_on_overflow. */
266 0, /* Special_function. */
268 FALSE
, /* Partial_inplace. */
269 0, /* Source mask. */
271 FALSE
), /* PC rel offset. */
276 /* TOC relative indirect load. */
277 HOWTO (0x12, /* Type. */
279 2, /* Size (0 = byte, 1 = short, 2 = long). */
281 FALSE
, /* PC relative. */
283 complain_overflow_bitfield
, /* Complain_on_overflow. */
284 0, /* Special_function. */
286 TRUE
, /* Partial_inplace. */
287 0xffff, /* Source mask. */
288 0xffff, /* Dest mask. */
289 FALSE
), /* PC rel offset. */
291 /* TOC relative load address. */
292 HOWTO (0x13, /* Type. */
294 2, /* Size (0 = byte, 1 = short, 2 = long). */
296 FALSE
, /* PC relative. */
298 complain_overflow_bitfield
, /* Complain_on_overflow. */
299 0, /* Special_function. */
300 "R_TRLA", /* Name. */
301 TRUE
, /* Partial_inplace. */
302 0xffff, /* Source mask. */
303 0xffff, /* Dest mask. */
304 FALSE
), /* PC rel offset. */
306 /* Modifiable relative branch. */
307 HOWTO (0x14, /* Type. */
309 2, /* Size (0 = byte, 1 = short, 2 = long). */
311 FALSE
, /* PC relative. */
313 complain_overflow_bitfield
, /* Complain_on_overflow. */
314 0, /* Special_function. */
315 "R_RRTBI", /* Name. */
316 TRUE
, /* Partial_inplace. */
317 0xffffffff, /* Source mask. */
318 0xffffffff, /* Dest mask. */
319 FALSE
), /* PC rel offset. */
321 /* Modifiable absolute branch. */
322 HOWTO (0x15, /* Type. */
324 2, /* Size (0 = byte, 1 = short, 2 = long). */
326 FALSE
, /* PC relative. */
328 complain_overflow_bitfield
, /* Complain_on_overflow. */
329 0, /* Special_function. */
330 "R_RRTBA", /* Name. */
331 TRUE
, /* Partial_inplace. */
332 0xffffffff, /* Source mask. */
333 0xffffffff, /* Dest mask. */
334 FALSE
), /* PC rel offset. */
336 /* Modifiable call absolute indirect. */
337 HOWTO (0x16, /* Type. */
339 2, /* Size (0 = byte, 1 = short, 2 = long). */
341 FALSE
, /* PC relative. */
343 complain_overflow_bitfield
, /* Complain_on_overflow. */
344 0, /* Special_function. */
346 TRUE
, /* Partial_inplace. */
347 0xffff, /* Source mask. */
348 0xffff, /* Dest mask. */
349 FALSE
), /* PC rel offset. */
351 /* Modifiable call relative. */
352 HOWTO (0x17, /* Type. */
354 2, /* Size (0 = byte, 1 = short, 2 = long). */
356 FALSE
, /* PC relative. */
358 complain_overflow_bitfield
, /* Complain_on_overflow. */
359 0, /* Special_function. */
361 TRUE
, /* Partial_inplace. */
362 0xffff, /* Source mask. */
363 0xffff, /* Dest mask. */
364 FALSE
), /* PC rel offset. */
366 /* Modifiable branch absolute. */
367 HOWTO (0x18, /* Type. */
369 2, /* Size (0 = byte, 1 = short, 2 = long). */
371 FALSE
, /* PC relative. */
373 complain_overflow_bitfield
, /* Complain_on_overflow. */
374 0, /* Special_function. */
376 TRUE
, /* Partial_inplace. */
377 0xffff, /* Source mask. */
378 0xffff, /* Dest mask. */
379 FALSE
), /* PC rel offset. */
381 /* Modifiable branch absolute. */
382 HOWTO (0x19, /* Type. */
384 2, /* Size (0 = byte, 1 = short, 2 = long). */
386 FALSE
, /* PC relative. */
388 complain_overflow_bitfield
, /* Complain_on_overflow. */
389 0, /* Special_function. */
390 "R_RBAC", /* Name. */
391 TRUE
, /* Partial_inplace. */
392 0xffff, /* Source mask. */
393 0xffff, /* Dest mask. */
394 FALSE
), /* PC rel offset. */
396 /* Modifiable branch relative. */
397 HOWTO (0x1a, /* Type. */
399 2, /* Size (0 = byte, 1 = short, 2 = long). */
401 FALSE
, /* PC relative. */
403 complain_overflow_signed
, /* Complain_on_overflow. */
404 0, /* Special_function. */
406 TRUE
, /* Partial_inplace. */
407 0xffff, /* Source mask. */
408 0xffff, /* Dest mask. */
409 FALSE
), /* PC rel offset. */
411 /* Modifiable branch absolute. */
412 HOWTO (0x1b, /* Type. */
414 2, /* Size (0 = byte, 1 = short, 2 = long). */
416 FALSE
, /* PC relative. */
418 complain_overflow_bitfield
, /* Complain_on_overflow. */
419 0, /* Special_function. */
421 TRUE
, /* Partial_inplace. */
422 0xffff, /* Source mask. */
423 0xffff, /* Dest mask. */
424 FALSE
) /* PC rel offset. */
427 #define HOWTO_COUNT (sizeof nlm_powerpc_howto_table \
428 / sizeof nlm_powerpc_howto_table[0])
430 /* Read a PowerPC NLM reloc. */
433 nlm_powerpc_read_reloc (bfd
*abfd
,
434 nlmNAME (symbol_type
) *sym
,
438 struct nlm32_powerpc_external_reloc ext
;
440 unsigned long l_symndx
;
443 asection
*code_sec
, *data_sec
, *bss_sec
;
445 /* Read the reloc from the file. */
446 if (bfd_bread (&ext
, (bfd_size_type
) sizeof ext
, abfd
) != sizeof ext
)
449 /* Swap in the fields. */
450 l_vaddr
= H_GET_32 (abfd
, ext
.l_vaddr
);
451 l_symndx
= H_GET_32 (abfd
, ext
.l_symndx
);
452 l_rtype
= H_GET_16 (abfd
, ext
.l_rtype
);
453 l_rsecnm
= H_GET_16 (abfd
, ext
.l_rsecnm
);
455 /* Get the sections now, for convenience. */
456 code_sec
= bfd_get_section_by_name (abfd
, NLM_CODE_NAME
);
457 data_sec
= bfd_get_section_by_name (abfd
, NLM_INITIALIZED_DATA_NAME
);
458 bss_sec
= bfd_get_section_by_name (abfd
, NLM_UNINITIALIZED_DATA_NAME
);
460 /* Work out the arelent fields. */
462 /* This is an import. sym_ptr_ptr is filled in by
463 nlm_canonicalize_reloc. */
464 rel
->sym_ptr_ptr
= NULL
;
471 else if (l_symndx
== 1)
473 else if (l_symndx
== 2)
477 bfd_set_error (bfd_error_bad_value
);
481 rel
->sym_ptr_ptr
= sec
->symbol_ptr_ptr
;
486 BFD_ASSERT ((l_rtype
& 0xff) < HOWTO_COUNT
);
488 rel
->howto
= nlm_powerpc_howto_table
+ (l_rtype
& 0xff);
490 BFD_ASSERT (rel
->howto
->name
!= NULL
491 && ((l_rtype
& 0x8000) != 0
492 ? (rel
->howto
->complain_on_overflow
493 == complain_overflow_signed
)
494 : (rel
->howto
->complain_on_overflow
495 == complain_overflow_bitfield
))
496 && ((l_rtype
>> 8) & 0x1f) == rel
->howto
->bitsize
- 1);
500 else if (l_rsecnm
== 1)
503 l_vaddr
-= code_sec
->size
;
507 bfd_set_error (bfd_error_bad_value
);
511 rel
->address
= l_vaddr
;
516 #else /* not OLDFORMAT */
518 /* There is only one type of reloc in a PowerPC NLM. */
520 static reloc_howto_type nlm_powerpc_howto
=
521 HOWTO (0, /* Type. */
523 2, /* Size (0 = byte, 1 = short, 2 = long). */
525 FALSE
, /* PC relative. */
527 complain_overflow_bitfield
, /* Complain_on_overflow. */
528 0, /* Special_function. */
530 TRUE
, /* Partial_inplace. */
531 0xffffffff, /* Source mask. */
532 0xffffffff, /* Dest mask. */
533 FALSE
); /* PC rel_offset. */
535 /* Read a PowerPC NLM reloc. */
538 nlm_powerpc_read_reloc (bfd
*abfd
,
539 nlmNAME (symbol_type
) *sym
,
547 if (bfd_bread (temp
, (bfd_size_type
) sizeof (temp
), abfd
) != sizeof (temp
))
550 val
= bfd_get_32 (abfd
, temp
);
552 /* The value is a word offset into either the code or data segment.
553 This is the location which needs to be adjusted.
555 The high bit is 0 if the value is an offset into the data
556 segment, or 1 if the value is an offset into the text segment.
558 If this is a relocation fixup rather than an imported symbol (the
559 sym argument is NULL), then the second most significant bit is 0
560 if the address of the data segment should be added to the
561 location addressed by the value, or 1 if the address of the text
562 segment should be added.
564 If this is an imported symbol, the second most significant bit is
565 not used and must be 0. */
567 if ((val
& NLM_HIBIT
) == 0)
568 name
= NLM_INITIALIZED_DATA_NAME
;
571 name
= NLM_CODE_NAME
;
574 *secp
= bfd_get_section_by_name (abfd
, name
);
578 if ((val
& (NLM_HIBIT
>> 1)) == 0)
579 name
= NLM_INITIALIZED_DATA_NAME
;
582 name
= NLM_CODE_NAME
;
583 val
&=~ (NLM_HIBIT
>> 1);
585 rel
->sym_ptr_ptr
= bfd_get_section_by_name (abfd
, name
)->symbol_ptr_ptr
;
588 rel
->howto
= & nlm_powerpc_howto
;
589 rel
->address
= val
<< 2;
595 #endif /* not OLDFORMAT */
597 /* Mangle PowerPC NLM relocs for output. */
600 nlm_powerpc_mangle_relocs (bfd
*abfd ATTRIBUTE_UNUSED
,
601 asection
*sec ATTRIBUTE_UNUSED
,
602 const void * data ATTRIBUTE_UNUSED
,
603 bfd_vma offset ATTRIBUTE_UNUSED
,
604 bfd_size_type count ATTRIBUTE_UNUSED
)
609 /* Read a PowerPC NLM import record */
612 nlm_powerpc_read_import (bfd
* abfd
, nlmNAME (symbol_type
) * sym
)
614 struct nlm_relent
*nlm_relocs
; /* Relocation records for symbol. */
615 bfd_size_type rcount
; /* Number of relocs. */
616 bfd_byte temp
[NLM_TARGET_LONG_SIZE
]; /* Temporary 32-bit value. */
617 unsigned char symlength
; /* Length of symbol name. */
620 if (bfd_bread (& symlength
, (bfd_size_type
) sizeof (symlength
), abfd
)
621 != sizeof (symlength
))
623 sym
-> symbol
.the_bfd
= abfd
;
624 name
= bfd_alloc (abfd
, (bfd_size_type
) symlength
+ 1);
627 if (bfd_bread (name
, (bfd_size_type
) symlength
, abfd
) != symlength
)
629 name
[symlength
] = '\0';
630 sym
-> symbol
.name
= name
;
631 sym
-> symbol
.flags
= 0;
632 sym
-> symbol
.value
= 0;
633 sym
-> symbol
.section
= bfd_und_section_ptr
;
634 if (bfd_bread (temp
, (bfd_size_type
) sizeof (temp
), abfd
)
637 rcount
= H_GET_32 (abfd
, temp
);
638 nlm_relocs
= bfd_alloc (abfd
, rcount
* sizeof (struct nlm_relent
));
639 if (nlm_relocs
== NULL
)
641 sym
-> relocs
= nlm_relocs
;
643 while (sym
-> rcnt
< rcount
)
647 if (! nlm_powerpc_read_reloc (abfd
, sym
, §ion
, &nlm_relocs
-> reloc
))
649 nlm_relocs
-> section
= section
;
658 /* Write a PowerPC NLM reloc. */
661 nlm_powerpc_write_import (bfd
* abfd
, asection
* sec
, arelent
* rel
)
667 /* PowerPC NetWare only supports one kind of reloc. */
669 || rel
->howto
== NULL
670 || rel
->howto
->rightshift
!= 0
671 || rel
->howto
->size
!= 2
672 || rel
->howto
->bitsize
!= 32
673 || rel
->howto
->bitpos
!= 0
674 || rel
->howto
->pc_relative
675 || (rel
->howto
->src_mask
!= 0xffffffff && rel
->addend
!= 0)
676 || rel
->howto
->dst_mask
!= 0xffffffff)
678 bfd_set_error (bfd_error_invalid_operation
);
682 sym
= *rel
->sym_ptr_ptr
;
684 /* The value we write out is the offset into the appropriate
685 segment, rightshifted by two. This offset is the section vma,
686 adjusted by the vma of the lowest section in that segment, plus
687 the address of the relocation. */
688 val
= bfd_get_section_vma (abfd
, sec
) + rel
->address
;
691 bfd_set_error (bfd_error_bad_value
);
696 /* The high bit is 0 if the reloc is in the data section, or 1 if
697 the reloc is in the code section. */
698 if (bfd_get_section_flags (abfd
, sec
) & SEC_DATA
)
699 val
-= nlm_get_data_low (abfd
);
702 val
-= nlm_get_text_low (abfd
);
706 if (! bfd_is_und_section (bfd_get_section (sym
)))
708 /* This is an internal relocation fixup. The second most
709 significant bit is 0 if this is a reloc against the data
710 segment, or 1 if it is a reloc against the text segment. */
711 if (bfd_get_section_flags (abfd
, bfd_get_section (sym
)) & SEC_CODE
)
712 val
|= NLM_HIBIT
>> 1;
715 bfd_put_32 (abfd
, val
, temp
);
716 if (bfd_bwrite (temp
, (bfd_size_type
) sizeof (temp
), abfd
) != sizeof (temp
))
722 #else /* OLDFORMAT */
724 /* This is used for the reloc handling in the old format. */
726 /* Write a PowerPC NLM reloc. */
729 nlm_powerpc_write_reloc (bfd
*abfd
,
734 struct nlm32_powerpc_external_reloc ext
;
735 asection
*code_sec
, *data_sec
, *bss_sec
;
738 unsigned long l_symndx
;
741 reloc_howto_type
*howto
;
742 bfd_size_type address
;
744 /* Get the sections now, for convenience. */
745 code_sec
= bfd_get_section_by_name (abfd
, NLM_CODE_NAME
);
746 data_sec
= bfd_get_section_by_name (abfd
, NLM_INITIALIZED_DATA_NAME
);
747 bss_sec
= bfd_get_section_by_name (abfd
, NLM_UNINITIALIZED_DATA_NAME
);
749 sym
= *rel
->sym_ptr_ptr
;
750 symsec
= bfd_get_section (sym
);
753 BFD_ASSERT (bfd_is_und_section (symsec
));
758 if (symsec
== code_sec
)
760 else if (symsec
== data_sec
)
762 else if (symsec
== bss_sec
)
766 bfd_set_error (bfd_error_bad_value
);
771 H_PUT_32 (abfd
, l_symndx
, ext
.l_symndx
);
773 for (howto
= nlm_powerpc_howto_table
;
774 howto
< nlm_powerpc_howto_table
+ HOWTO_COUNT
;
777 if (howto
->rightshift
== rel
->howto
->rightshift
778 && howto
->size
== rel
->howto
->size
779 && howto
->bitsize
== rel
->howto
->bitsize
780 && howto
->pc_relative
== rel
->howto
->pc_relative
781 && howto
->bitpos
== rel
->howto
->bitpos
782 && (howto
->partial_inplace
== rel
->howto
->partial_inplace
783 || (! rel
->howto
->partial_inplace
784 && rel
->addend
== 0))
785 && (howto
->src_mask
== rel
->howto
->src_mask
786 || (rel
->howto
->src_mask
== 0
787 && rel
->addend
== 0))
788 && howto
->dst_mask
== rel
->howto
->dst_mask
789 && howto
->pcrel_offset
== rel
->howto
->pcrel_offset
)
792 if (howto
>= nlm_powerpc_howto_table
+ HOWTO_COUNT
)
794 bfd_set_error (bfd_error_bad_value
);
798 l_rtype
= howto
->type
;
799 if (howto
->complain_on_overflow
== complain_overflow_signed
)
801 l_rtype
|= (howto
->bitsize
- 1) << 8;
802 H_PUT_16 (abfd
, l_rtype
, ext
.l_rtype
);
804 address
= rel
->address
;
808 else if (sec
== data_sec
)
811 address
+= code_sec
->size
;
815 bfd_set_error (bfd_error_bad_value
);
819 H_PUT_16 (abfd
, l_rsecnm
, ext
.l_rsecnm
);
820 H_PUT_32 (abfd
, address
, ext
.l_vaddr
);
822 if (bfd_bwrite (&ext
, (bfd_size_type
) sizeof ext
, abfd
) != sizeof ext
)
828 /* Write a PowerPC NLM import. */
831 nlm_powerpc_write_import (bfd
* abfd
, asection
* sec
, arelent
* rel
)
833 return nlm_powerpc_write_reloc (abfd
, sec
, rel
, -1);
836 #endif /* OLDFORMAT */
838 /* Write a PowerPC NLM external symbol. This routine keeps a static
839 count of the symbol index. FIXME: I don't know if this is
840 necessary, and the index never gets reset. */
843 nlm_powerpc_write_external (bfd
*abfd
,
846 struct reloc_and_sec
*relocs
)
850 unsigned char temp
[NLM_TARGET_LONG_SIZE
];
855 len
= strlen (sym
->name
);
856 if ((bfd_bwrite (&len
, (bfd_size_type
) sizeof (bfd_byte
), abfd
)
857 != sizeof (bfd_byte
))
858 || bfd_bwrite (sym
->name
, (bfd_size_type
) len
, abfd
) != len
)
861 bfd_put_32 (abfd
, count
, temp
);
862 if (bfd_bwrite (temp
, (bfd_size_type
) sizeof (temp
), abfd
) != sizeof (temp
))
865 for (i
= 0; i
< count
; i
++)
868 if (! nlm_powerpc_write_import (abfd
, relocs
[i
].sec
, relocs
[i
].rel
))
871 if (! nlm_powerpc_write_reloc (abfd
, relocs
[i
].sec
,
872 relocs
[i
].rel
, indx
))
886 /* PowerPC Netware uses a word offset, not a byte offset, for public
889 /* Set the section for a public symbol. */
892 nlm_powerpc_set_public_section (bfd
*abfd
, nlmNAME (symbol_type
) *sym
)
894 if (sym
->symbol
.value
& NLM_HIBIT
)
896 sym
->symbol
.value
&= ~NLM_HIBIT
;
897 sym
->symbol
.flags
|= BSF_FUNCTION
;
898 sym
->symbol
.section
=
899 bfd_get_section_by_name (abfd
, NLM_CODE_NAME
);
902 sym
->symbol
.section
=
903 bfd_get_section_by_name (abfd
, NLM_INITIALIZED_DATA_NAME
);
905 sym
->symbol
.value
<<= 2;
910 /* Get the offset to write out for a public symbol. */
913 nlm_powerpc_get_public_offset (bfd
*abfd
, asymbol
*sym
)
918 offset
= bfd_asymbol_value (sym
);
919 sec
= bfd_get_section (sym
);
920 if (sec
->flags
& SEC_CODE
)
922 offset
-= nlm_get_text_low (abfd
);
925 else if (sec
->flags
& (SEC_DATA
| SEC_ALLOC
))
927 /* SEC_ALLOC is for the .bss section. */
928 offset
-= nlm_get_data_low (abfd
);
932 /* We can't handle an exported symbol that is not in the code or
934 bfd_set_error (bfd_error_invalid_operation
);
935 /* FIXME: No way to return error. */
942 #endif /* ! defined (OLDFORMAT) */
946 static const struct nlm_backend_data nlm32_powerpc_backend
=
948 "NetWare PowerPC Module \032",
949 sizeof (Nlm32_powerpc_External_Fixed_Header
),
951 0, /* Optional_prefix_size. */
953 sizeof (struct nlm32_powerpc_external_prefix_header
),
959 0, /* Backend_object_p. */
960 0, /* Write_prefix. */
962 nlm_powerpc_backend_object_p
,
963 nlm_powerpc_write_prefix
,
965 nlm_powerpc_read_reloc
,
966 nlm_powerpc_mangle_relocs
,
967 nlm_powerpc_read_import
,
968 nlm_powerpc_write_import
,
970 nlm_powerpc_set_public_section
,
971 nlm_powerpc_get_public_offset
,
973 0, /* Set_public_section. */
974 0, /* Get_public_offset. */
976 nlm_swap_fixed_header_in
,
977 nlm_swap_fixed_header_out
,
978 nlm_powerpc_write_external
,
979 0, /* Write_export. */
982 #define TARGET_BIG_NAME "nlm32-powerpc"
983 #define TARGET_BIG_SYM powerpc_nlm32_vec
984 #define TARGET_BACKEND_DATA & nlm32_powerpc_backend
986 #include "nlm-target.h"