1 /* Support for 32-bit PowerPC NLM (NetWare Loadable Module)
2 Copyright 1994, 1995, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
3 2007 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
26 /* The format of a PowerPC NLM changed. Define OLDFORMAT to get the
31 #include "nlm/ppc-ext.h"
32 #define Nlm_External_Fixed_Header Nlm32_powerpc_External_Fixed_Header
38 /* The prefix header is only used in the old format. */
40 /* PowerPC NLM's have a prefix header before the standard NLM. This
41 function reads it in, verifies the version, and seeks the bfd to
42 the location before the regular NLM header. */
45 nlm_powerpc_backend_object_p (bfd *abfd)
47 struct nlm32_powerpc_external_prefix_header s;
49 if (bfd_bread (& s, (bfd_size_type) sizeof s, abfd) != sizeof s)
52 if (memcmp (s.signature, NLM32_POWERPC_SIGNATURE, sizeof s.signature) != 0
53 || H_GET_32 (abfd, s.headerVersion) != NLM32_POWERPC_HEADER_VERSION)
59 /* Write out the prefix. */
62 nlm_powerpc_write_prefix (bfd *abfd)
64 struct nlm32_powerpc_external_prefix_header s;
66 memset (&s, 0, sizeof s);
67 memcpy (s.signature, NLM32_POWERPC_SIGNATURE, sizeof s.signature);
68 H_PUT_32 (abfd, NLM32_POWERPC_HEADER_VERSION, s.headerVersion);
69 H_PUT_32 (abfd, 0, s.origins);
71 /* FIXME: What should we do about the date? */
73 if (bfd_bwrite (& s, (bfd_size_type) sizeof s, abfd) != sizeof s)
79 /* This reloc handling is only applicable to the old format. */
81 /* How to process the various reloc types. PowerPC NLMs use XCOFF
82 reloc types, and I have just copied the XCOFF reloc table here. */
84 static reloc_howto_type nlm_powerpc_howto_table[] =
86 /* Standard 32 bit relocation. */
89 2, /* Size (0 = byte, 1 = short, 2 = long). */
91 FALSE, /* PC relative. */
93 complain_overflow_bitfield, /* Complain_on_overflow. */
94 0, /* Special_function. */
96 TRUE, /* Partial_inplace. */
97 0xffffffff, /* Source mask. */
98 0xffffffff, /* Dest mask. */
99 FALSE), /* PC rel offset. */
101 /* 32 bit relocation, but store negative value. */
102 HOWTO (1, /* Type. */
104 -2, /* Size (0 = byte, 1 = short, 2 = long). */
106 FALSE, /* PC relative. */
108 complain_overflow_bitfield, /* Complain_on_overflow. */
109 0, /* Special_function. */
111 TRUE, /* Partial_inplace. */
112 0xffffffff, /* Source mask. */
113 0xffffffff, /* Dest mask. */
114 FALSE), /* PC rel offset. */
116 /* 32 bit PC relative relocation. */
117 HOWTO (2, /* Type. */
119 2, /* Size (0 = byte, 1 = short, 2 = long). */
121 TRUE, /* PC relative. */
123 complain_overflow_signed, /* Complain_on_overflow. */
124 0, /* Special_function. */
126 TRUE, /* Partial_inplace. */
127 0xffffffff, /* Source mask. */
128 0xffffffff, /* Dest mask. */
129 FALSE), /* PC rel offset. */
131 /* 16 bit TOC relative relocation. */
132 HOWTO (3, /* Type. */
134 1, /* Size (0 = byte, 1 = short, 2 = long). */
136 FALSE, /* PC relative. */
138 complain_overflow_signed, /* Complain_on_overflow. */
139 0, /* Special_function. */
141 TRUE, /* Partial_inplace. */
142 0xffff, /* Source mask. */
143 0xffff, /* Dest mask. */
144 FALSE), /* PC rel offset. */
146 /* I don't really know what this is. */
147 HOWTO (4, /* Type. */
149 2, /* Size (0 = byte, 1 = short, 2 = long). */
151 FALSE, /* PC relative. */
153 complain_overflow_bitfield, /* Complain_on_overflow. */
154 0, /* Special_function. */
156 TRUE, /* Partial_inplace. */
157 0xffffffff, /* Source mask. */
158 0xffffffff, /* Dest mask. */
159 FALSE), /* PC rel offset. */
161 /* External TOC relative symbol. */
162 HOWTO (5, /* Type. */
164 2, /* Size (0 = byte, 1 = short, 2 = long). */
166 FALSE, /* PC relative. */
168 complain_overflow_bitfield, /* Complain_on_overflow. */
169 0, /* Special_function. */
171 TRUE, /* Partial_inplace. */
172 0xffff, /* Source mask. */
173 0xffff, /* Dest mask. */
174 FALSE), /* PC rel offset. */
176 /* Local TOC relative symbol. */
177 HOWTO (6, /* Type. */
179 2, /* Size (0 = byte, 1 = short, 2 = long). */
181 FALSE, /* PC relative. */
183 complain_overflow_bitfield, /* Complain_on_overflow. */
184 0, /* Special_function. */
186 TRUE, /* Partial_inplace. */
187 0xffff, /* Source mask. */
188 0xffff, /* Dest mask. */
189 FALSE), /* PC rel offset. */
193 /* Non modifiable absolute branch. */
194 HOWTO (8, /* Type. */
196 2, /* Size (0 = byte, 1 = short, 2 = long). */
198 FALSE, /* PC relative. */
200 complain_overflow_bitfield, /* Complain_on_overflow. */
201 0, /* Special_function. */
203 TRUE, /* Partial_inplace. */
204 0x3fffffc, /* Source mask. */
205 0x3fffffc, /* Dest mask. */
206 FALSE), /* PC rel offset. */
210 /* Non modifiable relative branch. */
211 HOWTO (0xa, /* Type. */
213 2, /* Size (0 = byte, 1 = short, 2 = long). */
215 TRUE, /* PC relative. */
217 complain_overflow_signed, /* Complain_on_overflow. */
218 0, /* Special_function. */
220 TRUE, /* Partial_inplace. */
221 0x3fffffc, /* Source mask. */
222 0x3fffffc, /* Dest mask. */
223 FALSE), /* PC rel offset. */
228 HOWTO (0xc, /* Type. */
230 2, /* Size (0 = byte, 1 = short, 2 = long). */
232 FALSE, /* PC relative. */
234 complain_overflow_bitfield, /* Complain_on_overflow. */
235 0, /* Special_function. */
237 TRUE, /* Partial_inplace. */
238 0xffff, /* Source mask. */
239 0xffff, /* Dest mask. */
240 FALSE), /* PC rel offset. */
243 HOWTO (0xd, /* Type. */
245 2, /* Size (0 = byte, 1 = short, 2 = long). */
247 FALSE, /* PC relative. */
249 complain_overflow_bitfield, /* Complain_on_overflow. */
250 0, /* Special_function. */
252 TRUE, /* Partial_inplace. */
253 0xffff, /* Source mask. */
254 0xffff, /* Dest mask. */
255 FALSE), /* PC rel offset. */
259 /* Non-relocating reference. */
260 HOWTO (0xf, /* Type. */
262 2, /* Size (0 = byte, 1 = short, 2 = long). */
264 FALSE, /* PC relative. */
266 complain_overflow_bitfield, /* Complain_on_overflow. */
267 0, /* Special_function. */
269 FALSE, /* Partial_inplace. */
270 0, /* Source mask. */
272 FALSE), /* PC rel offset. */
277 /* TOC relative indirect load. */
278 HOWTO (0x12, /* Type. */
280 2, /* Size (0 = byte, 1 = short, 2 = long). */
282 FALSE, /* PC relative. */
284 complain_overflow_bitfield, /* Complain_on_overflow. */
285 0, /* Special_function. */
287 TRUE, /* Partial_inplace. */
288 0xffff, /* Source mask. */
289 0xffff, /* Dest mask. */
290 FALSE), /* PC rel offset. */
292 /* TOC relative load address. */
293 HOWTO (0x13, /* Type. */
295 2, /* Size (0 = byte, 1 = short, 2 = long). */
297 FALSE, /* PC relative. */
299 complain_overflow_bitfield, /* Complain_on_overflow. */
300 0, /* Special_function. */
301 "R_TRLA", /* Name. */
302 TRUE, /* Partial_inplace. */
303 0xffff, /* Source mask. */
304 0xffff, /* Dest mask. */
305 FALSE), /* PC rel offset. */
307 /* Modifiable relative branch. */
308 HOWTO (0x14, /* Type. */
310 2, /* Size (0 = byte, 1 = short, 2 = long). */
312 FALSE, /* PC relative. */
314 complain_overflow_bitfield, /* Complain_on_overflow. */
315 0, /* Special_function. */
316 "R_RRTBI", /* Name. */
317 TRUE, /* Partial_inplace. */
318 0xffffffff, /* Source mask. */
319 0xffffffff, /* Dest mask. */
320 FALSE), /* PC rel offset. */
322 /* Modifiable absolute branch. */
323 HOWTO (0x15, /* Type. */
325 2, /* Size (0 = byte, 1 = short, 2 = long). */
327 FALSE, /* PC relative. */
329 complain_overflow_bitfield, /* Complain_on_overflow. */
330 0, /* Special_function. */
331 "R_RRTBA", /* Name. */
332 TRUE, /* Partial_inplace. */
333 0xffffffff, /* Source mask. */
334 0xffffffff, /* Dest mask. */
335 FALSE), /* PC rel offset. */
337 /* Modifiable call absolute indirect. */
338 HOWTO (0x16, /* Type. */
340 2, /* Size (0 = byte, 1 = short, 2 = long). */
342 FALSE, /* PC relative. */
344 complain_overflow_bitfield, /* Complain_on_overflow. */
345 0, /* Special_function. */
347 TRUE, /* Partial_inplace. */
348 0xffff, /* Source mask. */
349 0xffff, /* Dest mask. */
350 FALSE), /* PC rel offset. */
352 /* Modifiable call relative. */
353 HOWTO (0x17, /* Type. */
355 2, /* Size (0 = byte, 1 = short, 2 = long). */
357 FALSE, /* PC relative. */
359 complain_overflow_bitfield, /* Complain_on_overflow. */
360 0, /* Special_function. */
362 TRUE, /* Partial_inplace. */
363 0xffff, /* Source mask. */
364 0xffff, /* Dest mask. */
365 FALSE), /* PC rel offset. */
367 /* Modifiable branch absolute. */
368 HOWTO (0x18, /* Type. */
370 2, /* Size (0 = byte, 1 = short, 2 = long). */
372 FALSE, /* PC relative. */
374 complain_overflow_bitfield, /* Complain_on_overflow. */
375 0, /* Special_function. */
377 TRUE, /* Partial_inplace. */
378 0xffff, /* Source mask. */
379 0xffff, /* Dest mask. */
380 FALSE), /* PC rel offset. */
382 /* Modifiable branch absolute. */
383 HOWTO (0x19, /* Type. */
385 2, /* Size (0 = byte, 1 = short, 2 = long). */
387 FALSE, /* PC relative. */
389 complain_overflow_bitfield, /* Complain_on_overflow. */
390 0, /* Special_function. */
391 "R_RBAC", /* Name. */
392 TRUE, /* Partial_inplace. */
393 0xffff, /* Source mask. */
394 0xffff, /* Dest mask. */
395 FALSE), /* PC rel offset. */
397 /* Modifiable branch relative. */
398 HOWTO (0x1a, /* Type. */
400 2, /* Size (0 = byte, 1 = short, 2 = long). */
402 FALSE, /* PC relative. */
404 complain_overflow_signed, /* Complain_on_overflow. */
405 0, /* Special_function. */
407 TRUE, /* Partial_inplace. */
408 0xffff, /* Source mask. */
409 0xffff, /* Dest mask. */
410 FALSE), /* PC rel offset. */
412 /* Modifiable branch absolute. */
413 HOWTO (0x1b, /* Type. */
415 2, /* Size (0 = byte, 1 = short, 2 = long). */
417 FALSE, /* PC relative. */
419 complain_overflow_bitfield, /* Complain_on_overflow. */
420 0, /* Special_function. */
422 TRUE, /* Partial_inplace. */
423 0xffff, /* Source mask. */
424 0xffff, /* Dest mask. */
425 FALSE) /* PC rel offset. */
428 #define HOWTO_COUNT (sizeof nlm_powerpc_howto_table \
429 / sizeof nlm_powerpc_howto_table[0])
431 /* Read a PowerPC NLM reloc. */
434 nlm_powerpc_read_reloc (bfd *abfd,
435 nlmNAME (symbol_type) *sym,
439 struct nlm32_powerpc_external_reloc ext;
441 unsigned long l_symndx;
444 asection *code_sec, *data_sec, *bss_sec;
446 /* Read the reloc from the file. */
447 if (bfd_bread (&ext, (bfd_size_type) sizeof ext, abfd) != sizeof ext)
450 /* Swap in the fields. */
451 l_vaddr = H_GET_32 (abfd, ext.l_vaddr);
452 l_symndx = H_GET_32 (abfd, ext.l_symndx);
453 l_rtype = H_GET_16 (abfd, ext.l_rtype);
454 l_rsecnm = H_GET_16 (abfd, ext.l_rsecnm);
456 /* Get the sections now, for convenience. */
457 code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
458 data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
459 bss_sec = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
461 /* Work out the arelent fields. */
463 /* This is an import. sym_ptr_ptr is filled in by
464 nlm_canonicalize_reloc. */
465 rel->sym_ptr_ptr = NULL;
472 else if (l_symndx == 1)
474 else if (l_symndx == 2)
478 bfd_set_error (bfd_error_bad_value);
482 rel->sym_ptr_ptr = sec->symbol_ptr_ptr;
487 BFD_ASSERT ((l_rtype & 0xff) < HOWTO_COUNT);
489 rel->howto = nlm_powerpc_howto_table + (l_rtype & 0xff);
491 BFD_ASSERT (rel->howto->name != NULL
492 && ((l_rtype & 0x8000) != 0
493 ? (rel->howto->complain_on_overflow
494 == complain_overflow_signed)
495 : (rel->howto->complain_on_overflow
496 == complain_overflow_bitfield))
497 && ((l_rtype >> 8) & 0x1f) == rel->howto->bitsize - 1);
501 else if (l_rsecnm == 1)
504 l_vaddr -= code_sec->size;
508 bfd_set_error (bfd_error_bad_value);
512 rel->address = l_vaddr;
517 #else /* not OLDFORMAT */
519 /* There is only one type of reloc in a PowerPC NLM. */
521 static reloc_howto_type nlm_powerpc_howto =
522 HOWTO (0, /* Type. */
524 2, /* Size (0 = byte, 1 = short, 2 = long). */
526 FALSE, /* PC relative. */
528 complain_overflow_bitfield, /* Complain_on_overflow. */
529 0, /* Special_function. */
531 TRUE, /* Partial_inplace. */
532 0xffffffff, /* Source mask. */
533 0xffffffff, /* Dest mask. */
534 FALSE); /* PC rel_offset. */
536 /* Read a PowerPC NLM reloc. */
539 nlm_powerpc_read_reloc (bfd *abfd,
540 nlmNAME (symbol_type) *sym,
548 if (bfd_bread (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp))
551 val = bfd_get_32 (abfd, temp);
553 /* The value is a word offset into either the code or data segment.
554 This is the location which needs to be adjusted.
556 The high bit is 0 if the value is an offset into the data
557 segment, or 1 if the value is an offset into the text segment.
559 If this is a relocation fixup rather than an imported symbol (the
560 sym argument is NULL), then the second most significant bit is 0
561 if the address of the data segment should be added to the
562 location addressed by the value, or 1 if the address of the text
563 segment should be added.
565 If this is an imported symbol, the second most significant bit is
566 not used and must be 0. */
568 if ((val & NLM_HIBIT) == 0)
569 name = NLM_INITIALIZED_DATA_NAME;
572 name = NLM_CODE_NAME;
575 *secp = bfd_get_section_by_name (abfd, name);
579 if ((val & (NLM_HIBIT >> 1)) == 0)
580 name = NLM_INITIALIZED_DATA_NAME;
583 name = NLM_CODE_NAME;
584 val &=~ (NLM_HIBIT >> 1);
586 rel->sym_ptr_ptr = bfd_get_section_by_name (abfd, name)->symbol_ptr_ptr;
589 rel->howto = & nlm_powerpc_howto;
590 rel->address = val << 2;
596 #endif /* not OLDFORMAT */
598 /* Mangle PowerPC NLM relocs for output. */
601 nlm_powerpc_mangle_relocs (bfd *abfd ATTRIBUTE_UNUSED,
602 asection *sec ATTRIBUTE_UNUSED,
603 const void * data ATTRIBUTE_UNUSED,
604 bfd_vma offset ATTRIBUTE_UNUSED,
605 bfd_size_type count ATTRIBUTE_UNUSED)
610 /* Read a PowerPC NLM import record */
613 nlm_powerpc_read_import (bfd * abfd, nlmNAME (symbol_type) * sym)
615 struct nlm_relent *nlm_relocs; /* Relocation records for symbol. */
616 bfd_size_type rcount; /* Number of relocs. */
617 bfd_byte temp[NLM_TARGET_LONG_SIZE]; /* Temporary 32-bit value. */
618 unsigned char symlength; /* Length of symbol name. */
621 if (bfd_bread (& symlength, (bfd_size_type) sizeof (symlength), abfd)
622 != sizeof (symlength))
624 sym -> symbol.the_bfd = abfd;
625 name = bfd_alloc (abfd, (bfd_size_type) symlength + 1);
628 if (bfd_bread (name, (bfd_size_type) symlength, abfd) != symlength)
630 name[symlength] = '\0';
631 sym -> symbol.name = name;
632 sym -> symbol.flags = 0;
633 sym -> symbol.value = 0;
634 sym -> symbol.section = bfd_und_section_ptr;
635 if (bfd_bread (temp, (bfd_size_type) sizeof (temp), abfd)
638 rcount = H_GET_32 (abfd, temp);
639 nlm_relocs = bfd_alloc (abfd, rcount * sizeof (struct nlm_relent));
640 if (nlm_relocs == NULL)
642 sym -> relocs = nlm_relocs;
644 while (sym -> rcnt < rcount)
648 if (! nlm_powerpc_read_reloc (abfd, sym, §ion, &nlm_relocs -> reloc))
650 nlm_relocs -> section = section;
659 /* Write a PowerPC NLM reloc. */
662 nlm_powerpc_write_import (bfd * abfd, asection * sec, arelent * rel)
668 /* PowerPC NetWare only supports one kind of reloc. */
670 || rel->howto == NULL
671 || rel->howto->rightshift != 0
672 || rel->howto->size != 2
673 || rel->howto->bitsize != 32
674 || rel->howto->bitpos != 0
675 || rel->howto->pc_relative
676 || (rel->howto->src_mask != 0xffffffff && rel->addend != 0)
677 || rel->howto->dst_mask != 0xffffffff)
679 bfd_set_error (bfd_error_invalid_operation);
683 sym = *rel->sym_ptr_ptr;
685 /* The value we write out is the offset into the appropriate
686 segment, rightshifted by two. This offset is the section vma,
687 adjusted by the vma of the lowest section in that segment, plus
688 the address of the relocation. */
689 val = bfd_get_section_vma (abfd, sec) + rel->address;
692 bfd_set_error (bfd_error_bad_value);
697 /* The high bit is 0 if the reloc is in the data section, or 1 if
698 the reloc is in the code section. */
699 if (bfd_get_section_flags (abfd, sec) & SEC_DATA)
700 val -= nlm_get_data_low (abfd);
703 val -= nlm_get_text_low (abfd);
707 if (! bfd_is_und_section (bfd_get_section (sym)))
709 /* This is an internal relocation fixup. The second most
710 significant bit is 0 if this is a reloc against the data
711 segment, or 1 if it is a reloc against the text segment. */
712 if (bfd_get_section_flags (abfd, bfd_get_section (sym)) & SEC_CODE)
713 val |= NLM_HIBIT >> 1;
716 bfd_put_32 (abfd, val, temp);
717 if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp))
723 #else /* OLDFORMAT */
725 /* This is used for the reloc handling in the old format. */
727 /* Write a PowerPC NLM reloc. */
730 nlm_powerpc_write_reloc (bfd *abfd,
735 struct nlm32_powerpc_external_reloc ext;
736 asection *code_sec, *data_sec, *bss_sec;
739 unsigned long l_symndx;
742 reloc_howto_type *howto;
743 bfd_size_type address;
745 /* Get the sections now, for convenience. */
746 code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
747 data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
748 bss_sec = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
750 sym = *rel->sym_ptr_ptr;
751 symsec = bfd_get_section (sym);
754 BFD_ASSERT (bfd_is_und_section (symsec));
759 if (symsec == code_sec)
761 else if (symsec == data_sec)
763 else if (symsec == bss_sec)
767 bfd_set_error (bfd_error_bad_value);
772 H_PUT_32 (abfd, l_symndx, ext.l_symndx);
774 for (howto = nlm_powerpc_howto_table;
775 howto < nlm_powerpc_howto_table + HOWTO_COUNT;
778 if (howto->rightshift == rel->howto->rightshift
779 && howto->size == rel->howto->size
780 && howto->bitsize == rel->howto->bitsize
781 && howto->pc_relative == rel->howto->pc_relative
782 && howto->bitpos == rel->howto->bitpos
783 && (howto->partial_inplace == rel->howto->partial_inplace
784 || (! rel->howto->partial_inplace
785 && rel->addend == 0))
786 && (howto->src_mask == rel->howto->src_mask
787 || (rel->howto->src_mask == 0
788 && rel->addend == 0))
789 && howto->dst_mask == rel->howto->dst_mask
790 && howto->pcrel_offset == rel->howto->pcrel_offset)
793 if (howto >= nlm_powerpc_howto_table + HOWTO_COUNT)
795 bfd_set_error (bfd_error_bad_value);
799 l_rtype = howto->type;
800 if (howto->complain_on_overflow == complain_overflow_signed)
802 l_rtype |= (howto->bitsize - 1) << 8;
803 H_PUT_16 (abfd, l_rtype, ext.l_rtype);
805 address = rel->address;
809 else if (sec == data_sec)
812 address += code_sec->size;
816 bfd_set_error (bfd_error_bad_value);
820 H_PUT_16 (abfd, l_rsecnm, ext.l_rsecnm);
821 H_PUT_32 (abfd, address, ext.l_vaddr);
823 if (bfd_bwrite (&ext, (bfd_size_type) sizeof ext, abfd) != sizeof ext)
829 /* Write a PowerPC NLM import. */
832 nlm_powerpc_write_import (bfd * abfd, asection * sec, arelent * rel)
834 return nlm_powerpc_write_reloc (abfd, sec, rel, -1);
837 #endif /* OLDFORMAT */
839 /* Write a PowerPC NLM external symbol. This routine keeps a static
840 count of the symbol index. FIXME: I don't know if this is
841 necessary, and the index never gets reset. */
844 nlm_powerpc_write_external (bfd *abfd,
847 struct reloc_and_sec *relocs)
851 unsigned char temp[NLM_TARGET_LONG_SIZE];
856 len = strlen (sym->name);
857 if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd)
858 != sizeof (bfd_byte))
859 || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
862 bfd_put_32 (abfd, count, temp);
863 if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp))
866 for (i = 0; i < count; i++)
869 if (! nlm_powerpc_write_import (abfd, relocs[i].sec, relocs[i].rel))
872 if (! nlm_powerpc_write_reloc (abfd, relocs[i].sec,
873 relocs[i].rel, indx))
887 /* PowerPC Netware uses a word offset, not a byte offset, for public
890 /* Set the section for a public symbol. */
893 nlm_powerpc_set_public_section (bfd *abfd, nlmNAME (symbol_type) *sym)
895 if (sym->symbol.value & NLM_HIBIT)
897 sym->symbol.value &= ~NLM_HIBIT;
898 sym->symbol.flags |= BSF_FUNCTION;
899 sym->symbol.section =
900 bfd_get_section_by_name (abfd, NLM_CODE_NAME);
903 sym->symbol.section =
904 bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
906 sym->symbol.value <<= 2;
911 /* Get the offset to write out for a public symbol. */
914 nlm_powerpc_get_public_offset (bfd *abfd, asymbol *sym)
919 offset = bfd_asymbol_value (sym);
920 sec = bfd_get_section (sym);
921 if (sec->flags & SEC_CODE)
923 offset -= nlm_get_text_low (abfd);
926 else if (sec->flags & (SEC_DATA | SEC_ALLOC))
928 /* SEC_ALLOC is for the .bss section. */
929 offset -= nlm_get_data_low (abfd);
933 /* We can't handle an exported symbol that is not in the code or
935 bfd_set_error (bfd_error_invalid_operation);
936 /* FIXME: No way to return error. */
943 #endif /* ! defined (OLDFORMAT) */
947 static const struct nlm_backend_data nlm32_powerpc_backend =
949 "NetWare PowerPC Module \032",
950 sizeof (Nlm32_powerpc_External_Fixed_Header),
952 0, /* Optional_prefix_size. */
954 sizeof (struct nlm32_powerpc_external_prefix_header),
960 0, /* Backend_object_p. */
961 0, /* Write_prefix. */
963 nlm_powerpc_backend_object_p,
964 nlm_powerpc_write_prefix,
966 nlm_powerpc_read_reloc,
967 nlm_powerpc_mangle_relocs,
968 nlm_powerpc_read_import,
969 nlm_powerpc_write_import,
971 nlm_powerpc_set_public_section,
972 nlm_powerpc_get_public_offset,
974 0, /* Set_public_section. */
975 0, /* Get_public_offset. */
977 nlm_swap_fixed_header_in,
978 nlm_swap_fixed_header_out,
979 nlm_powerpc_write_external,
980 0, /* Write_export. */
983 #define TARGET_BIG_NAME "nlm32-powerpc"
984 #define TARGET_BIG_SYM nlmNAME (powerpc_vec)
985 #define TARGET_BACKEND_DATA & nlm32_powerpc_backend
987 #include "nlm-target.h"