12159047fSniklas /* Support for 32-bit PowerPC NLM (NetWare Loadable Module)
2*007c2a45Smiod Copyright 1994, 1995, 2000, 2001, 2002, 2003
3*007c2a45Smiod Free Software Foundation, Inc.
42159047fSniklas
52159047fSniklas This file is part of BFD, the Binary File Descriptor library.
62159047fSniklas
72159047fSniklas This program is free software; you can redistribute it and/or modify
82159047fSniklas it under the terms of the GNU General Public License as published by
92159047fSniklas the Free Software Foundation; either version 2 of the License, or
102159047fSniklas (at your option) any later version.
112159047fSniklas
122159047fSniklas This program is distributed in the hope that it will be useful,
132159047fSniklas but WITHOUT ANY WARRANTY; without even the implied warranty of
142159047fSniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
152159047fSniklas GNU General Public License for more details.
162159047fSniklas
172159047fSniklas You should have received a copy of the GNU General Public License
182159047fSniklas along with this program; if not, write to the Free Software
192159047fSniklas Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
202159047fSniklas
212159047fSniklas #include "bfd.h"
222159047fSniklas #include "sysdep.h"
232159047fSniklas #include "libbfd.h"
242159047fSniklas
252159047fSniklas /* The format of a PowerPC NLM changed. Define OLDFORMAT to get the
262159047fSniklas old format. */
272159047fSniklas
282159047fSniklas #define ARCH_SIZE 32
292159047fSniklas
302159047fSniklas #include "nlm/ppc-ext.h"
312159047fSniklas #define Nlm_External_Fixed_Header Nlm32_powerpc_External_Fixed_Header
322159047fSniklas
332159047fSniklas #include "libnlm.h"
342159047fSniklas
352159047fSniklas #ifdef OLDFORMAT
36c074d1c9Sdrahn static bfd_boolean nlm_powerpc_backend_object_p
372159047fSniklas PARAMS ((bfd *));
38c074d1c9Sdrahn static bfd_boolean nlm_powerpc_write_prefix
392159047fSniklas PARAMS ((bfd *));
402159047fSniklas #endif
412159047fSniklas
42c074d1c9Sdrahn static bfd_boolean nlm_powerpc_read_reloc
432159047fSniklas PARAMS ((bfd *, nlmNAME(symbol_type) *, asection **, arelent *));
44c074d1c9Sdrahn static bfd_boolean nlm_powerpc_mangle_relocs
45*007c2a45Smiod PARAMS ((bfd *, asection *, const PTR, bfd_vma, bfd_size_type));
46c074d1c9Sdrahn static bfd_boolean nlm_powerpc_read_import
472159047fSniklas PARAMS ((bfd *, nlmNAME(symbol_type) *));
482159047fSniklas
492159047fSniklas #ifdef OLDFORMAT
50c074d1c9Sdrahn static bfd_boolean nlm_powerpc_write_reloc
512159047fSniklas PARAMS ((bfd *, asection *, arelent *, int));
522159047fSniklas #endif
532159047fSniklas
54c074d1c9Sdrahn static bfd_boolean nlm_powerpc_write_import
552159047fSniklas PARAMS ((bfd *, asection *, arelent *));
56c074d1c9Sdrahn static bfd_boolean nlm_powerpc_write_external
572159047fSniklas PARAMS ((bfd *, bfd_size_type, asymbol *, struct reloc_and_sec *));
582159047fSniklas
592159047fSniklas #ifndef OLDFORMAT
60c074d1c9Sdrahn static bfd_boolean nlm_powerpc_set_public_section
612159047fSniklas PARAMS ((bfd *, nlmNAME(symbol_type) *));
622159047fSniklas static bfd_vma nlm_powerpc_get_public_offset
632159047fSniklas PARAMS ((bfd *, asymbol *));
642159047fSniklas #endif
652159047fSniklas
662159047fSniklas #ifdef OLDFORMAT
672159047fSniklas
682159047fSniklas /* The prefix header is only used in the old format. */
692159047fSniklas
702159047fSniklas /* PowerPC NLM's have a prefix header before the standard NLM. This
712159047fSniklas function reads it in, verifies the version, and seeks the bfd to
722159047fSniklas the location before the regular NLM header. */
732159047fSniklas
74c074d1c9Sdrahn static bfd_boolean
nlm_powerpc_backend_object_p(abfd)752159047fSniklas nlm_powerpc_backend_object_p (abfd)
762159047fSniklas bfd *abfd;
772159047fSniklas {
782159047fSniklas struct nlm32_powerpc_external_prefix_header s;
792159047fSniklas
80c074d1c9Sdrahn if (bfd_bread ((PTR) &s, (bfd_size_type) sizeof s, abfd) != sizeof s)
81c074d1c9Sdrahn return FALSE;
822159047fSniklas
832159047fSniklas if (memcmp (s.signature, NLM32_POWERPC_SIGNATURE, sizeof s.signature) != 0
84c074d1c9Sdrahn || H_GET_32 (abfd, s.headerVersion) != NLM32_POWERPC_HEADER_VERSION)
85c074d1c9Sdrahn return FALSE;
862159047fSniklas
87c074d1c9Sdrahn return TRUE;
882159047fSniklas }
892159047fSniklas
902159047fSniklas /* Write out the prefix. */
912159047fSniklas
92c074d1c9Sdrahn static bfd_boolean
nlm_powerpc_write_prefix(abfd)932159047fSniklas nlm_powerpc_write_prefix (abfd)
942159047fSniklas bfd *abfd;
952159047fSniklas {
962159047fSniklas struct nlm32_powerpc_external_prefix_header s;
972159047fSniklas
982159047fSniklas memset (&s, 0, sizeof s);
992159047fSniklas memcpy (s.signature, NLM32_POWERPC_SIGNATURE, sizeof s.signature);
100c074d1c9Sdrahn H_PUT_32 (abfd, NLM32_POWERPC_HEADER_VERSION, s.headerVersion);
101c074d1c9Sdrahn H_PUT_32 (abfd, 0, s.origins);
1022159047fSniklas
1032159047fSniklas /* FIXME: What should we do about the date? */
1042159047fSniklas
105c074d1c9Sdrahn if (bfd_bwrite ((PTR) &s, (bfd_size_type) sizeof s, abfd) != sizeof s)
106c074d1c9Sdrahn return FALSE;
1072159047fSniklas
108c074d1c9Sdrahn return TRUE;
1092159047fSniklas }
1102159047fSniklas
1112159047fSniklas #endif /* OLDFORMAT */
1122159047fSniklas
1132159047fSniklas #ifndef OLDFORMAT
1142159047fSniklas
1152159047fSniklas /* There is only one type of reloc in a PowerPC NLM. */
1162159047fSniklas
1172159047fSniklas static reloc_howto_type nlm_powerpc_howto =
1182159047fSniklas HOWTO (0, /* type */
1192159047fSniklas 0, /* rightshift */
1202159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
1212159047fSniklas 32, /* bitsize */
122c074d1c9Sdrahn FALSE, /* pc_relative */
1232159047fSniklas 0, /* bitpos */
1242159047fSniklas complain_overflow_bitfield, /* complain_on_overflow */
1252159047fSniklas 0, /* special_function */
1262159047fSniklas "32", /* name */
127c074d1c9Sdrahn TRUE, /* partial_inplace */
1282159047fSniklas 0xffffffff, /* src_mask */
1292159047fSniklas 0xffffffff, /* dst_mask */
130c074d1c9Sdrahn FALSE); /* pcrel_offset */
1312159047fSniklas
1322159047fSniklas /* Read a PowerPC NLM reloc. */
1332159047fSniklas
134c074d1c9Sdrahn static bfd_boolean
nlm_powerpc_read_reloc(abfd,sym,secp,rel)1352159047fSniklas nlm_powerpc_read_reloc (abfd, sym, secp, rel)
1362159047fSniklas bfd *abfd;
1372159047fSniklas nlmNAME(symbol_type) *sym;
1382159047fSniklas asection **secp;
1392159047fSniklas arelent *rel;
1402159047fSniklas {
1412159047fSniklas bfd_byte temp[4];
1422159047fSniklas bfd_vma val;
1432159047fSniklas const char *name;
1442159047fSniklas
145c074d1c9Sdrahn if (bfd_bread (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp))
146c074d1c9Sdrahn return FALSE;
1472159047fSniklas
1482159047fSniklas val = bfd_get_32 (abfd, temp);
1492159047fSniklas
1502159047fSniklas /* The value is a word offset into either the code or data segment.
1512159047fSniklas This is the location which needs to be adjusted.
1522159047fSniklas
1532159047fSniklas The high bit is 0 if the value is an offset into the data
1542159047fSniklas segment, or 1 if the value is an offset into the text segment.
1552159047fSniklas
1562159047fSniklas If this is a relocation fixup rather than an imported symbol (the
1572159047fSniklas sym argument is NULL), then the second most significant bit is 0
1582159047fSniklas if the address of the data segment should be added to the
1592159047fSniklas location addressed by the value, or 1 if the address of the text
1602159047fSniklas segment should be added.
1612159047fSniklas
1622159047fSniklas If this is an imported symbol, the second most significant bit is
1632159047fSniklas not used and must be 0. */
1642159047fSniklas
1652159047fSniklas if ((val & NLM_HIBIT) == 0)
1662159047fSniklas name = NLM_INITIALIZED_DATA_NAME;
1672159047fSniklas else
1682159047fSniklas {
1692159047fSniklas name = NLM_CODE_NAME;
1702159047fSniklas val &=~ NLM_HIBIT;
1712159047fSniklas }
1722159047fSniklas *secp = bfd_get_section_by_name (abfd, name);
1732159047fSniklas
1742159047fSniklas if (sym == NULL)
1752159047fSniklas {
1762159047fSniklas if ((val & (NLM_HIBIT >> 1)) == 0)
1772159047fSniklas name = NLM_INITIALIZED_DATA_NAME;
1782159047fSniklas else
1792159047fSniklas {
1802159047fSniklas name = NLM_CODE_NAME;
1812159047fSniklas val &=~ (NLM_HIBIT >> 1);
1822159047fSniklas }
1832159047fSniklas rel->sym_ptr_ptr = bfd_get_section_by_name (abfd, name)->symbol_ptr_ptr;
1842159047fSniklas }
1852159047fSniklas
1862159047fSniklas rel->howto = &nlm_powerpc_howto;
1872159047fSniklas
1882159047fSniklas rel->address = val << 2;
1892159047fSniklas rel->addend = 0;
1902159047fSniklas
191c074d1c9Sdrahn return TRUE;
1922159047fSniklas }
1932159047fSniklas
1942159047fSniklas #else /* OLDFORMAT */
1952159047fSniklas
1962159047fSniklas /* This reloc handling is only applicable to the old format. */
1972159047fSniklas
1982159047fSniklas /* How to process the various reloc types. PowerPC NLMs use XCOFF
1992159047fSniklas reloc types, and I have just copied the XCOFF reloc table here. */
2002159047fSniklas
2012159047fSniklas static reloc_howto_type nlm_powerpc_howto_table[] =
2022159047fSniklas {
2032159047fSniklas /* Standard 32 bit relocation. */
2042159047fSniklas HOWTO (0, /* type */
2052159047fSniklas 0, /* rightshift */
2062159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
2072159047fSniklas 32, /* bitsize */
208c074d1c9Sdrahn FALSE, /* pc_relative */
2092159047fSniklas 0, /* bitpos */
2102159047fSniklas complain_overflow_bitfield, /* complain_on_overflow */
2112159047fSniklas 0, /* special_function */
2122159047fSniklas "R_POS", /* name */
213c074d1c9Sdrahn TRUE, /* partial_inplace */
2142159047fSniklas 0xffffffff, /* src_mask */
2152159047fSniklas 0xffffffff, /* dst_mask */
216c074d1c9Sdrahn FALSE), /* pcrel_offset */
2172159047fSniklas
2182159047fSniklas /* 32 bit relocation, but store negative value. */
2192159047fSniklas HOWTO (1, /* type */
2202159047fSniklas 0, /* rightshift */
2212159047fSniklas -2, /* size (0 = byte, 1 = short, 2 = long) */
2222159047fSniklas 32, /* bitsize */
223c074d1c9Sdrahn FALSE, /* pc_relative */
2242159047fSniklas 0, /* bitpos */
2252159047fSniklas complain_overflow_bitfield, /* complain_on_overflow */
2262159047fSniklas 0, /* special_function */
2272159047fSniklas "R_NEG", /* name */
228c074d1c9Sdrahn TRUE, /* partial_inplace */
2292159047fSniklas 0xffffffff, /* src_mask */
2302159047fSniklas 0xffffffff, /* dst_mask */
231c074d1c9Sdrahn FALSE), /* pcrel_offset */
2322159047fSniklas
2332159047fSniklas /* 32 bit PC relative relocation. */
2342159047fSniklas HOWTO (2, /* type */
2352159047fSniklas 0, /* rightshift */
2362159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
2372159047fSniklas 32, /* bitsize */
238c074d1c9Sdrahn TRUE, /* pc_relative */
2392159047fSniklas 0, /* bitpos */
2402159047fSniklas complain_overflow_signed, /* complain_on_overflow */
2412159047fSniklas 0, /* special_function */
2422159047fSniklas "R_REL", /* name */
243c074d1c9Sdrahn TRUE, /* partial_inplace */
2442159047fSniklas 0xffffffff, /* src_mask */
2452159047fSniklas 0xffffffff, /* dst_mask */
246c074d1c9Sdrahn FALSE), /* pcrel_offset */
2472159047fSniklas
2482159047fSniklas /* 16 bit TOC relative relocation. */
2492159047fSniklas HOWTO (3, /* type */
2502159047fSniklas 0, /* rightshift */
2512159047fSniklas 1, /* size (0 = byte, 1 = short, 2 = long) */
2522159047fSniklas 16, /* bitsize */
253c074d1c9Sdrahn FALSE, /* pc_relative */
2542159047fSniklas 0, /* bitpos */
2552159047fSniklas complain_overflow_signed, /* complain_on_overflow */
2562159047fSniklas 0, /* special_function */
2572159047fSniklas "R_TOC", /* name */
258c074d1c9Sdrahn TRUE, /* partial_inplace */
2592159047fSniklas 0xffff, /* src_mask */
2602159047fSniklas 0xffff, /* dst_mask */
261c074d1c9Sdrahn FALSE), /* pcrel_offset */
2622159047fSniklas
2632159047fSniklas /* I don't really know what this is. */
2642159047fSniklas HOWTO (4, /* type */
2652159047fSniklas 1, /* rightshift */
2662159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
2672159047fSniklas 32, /* bitsize */
268c074d1c9Sdrahn FALSE, /* pc_relative */
2692159047fSniklas 0, /* bitpos */
2702159047fSniklas complain_overflow_bitfield, /* complain_on_overflow */
2712159047fSniklas 0, /* special_function */
2722159047fSniklas "R_RTB", /* name */
273c074d1c9Sdrahn TRUE, /* partial_inplace */
2742159047fSniklas 0xffffffff, /* src_mask */
2752159047fSniklas 0xffffffff, /* dst_mask */
276c074d1c9Sdrahn FALSE), /* pcrel_offset */
2772159047fSniklas
2782159047fSniklas /* External TOC relative symbol. */
2792159047fSniklas HOWTO (5, /* type */
2802159047fSniklas 0, /* rightshift */
2812159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
2822159047fSniklas 16, /* bitsize */
283c074d1c9Sdrahn FALSE, /* pc_relative */
2842159047fSniklas 0, /* bitpos */
2852159047fSniklas complain_overflow_bitfield, /* complain_on_overflow */
2862159047fSniklas 0, /* special_function */
2872159047fSniklas "R_GL", /* name */
288c074d1c9Sdrahn TRUE, /* partial_inplace */
2892159047fSniklas 0xffff, /* src_mask */
2902159047fSniklas 0xffff, /* dst_mask */
291c074d1c9Sdrahn FALSE), /* pcrel_offset */
2922159047fSniklas
2932159047fSniklas /* Local TOC relative symbol. */
2942159047fSniklas HOWTO (6, /* type */
2952159047fSniklas 0, /* rightshift */
2962159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
2972159047fSniklas 16, /* bitsize */
298c074d1c9Sdrahn FALSE, /* pc_relative */
2992159047fSniklas 0, /* bitpos */
3002159047fSniklas complain_overflow_bitfield, /* complain_on_overflow */
3012159047fSniklas 0, /* special_function */
3022159047fSniklas "R_TCL", /* name */
303c074d1c9Sdrahn TRUE, /* partial_inplace */
3042159047fSniklas 0xffff, /* src_mask */
3052159047fSniklas 0xffff, /* dst_mask */
306c074d1c9Sdrahn FALSE), /* pcrel_offset */
3072159047fSniklas
3082159047fSniklas { 7 },
3092159047fSniklas
3102159047fSniklas /* Non modifiable absolute branch. */
3112159047fSniklas HOWTO (8, /* type */
3122159047fSniklas 0, /* rightshift */
3132159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
3142159047fSniklas 26, /* bitsize */
315c074d1c9Sdrahn FALSE, /* pc_relative */
3162159047fSniklas 0, /* bitpos */
3172159047fSniklas complain_overflow_bitfield, /* complain_on_overflow */
3182159047fSniklas 0, /* special_function */
3192159047fSniklas "R_BA", /* name */
320c074d1c9Sdrahn TRUE, /* partial_inplace */
3212159047fSniklas 0x3fffffc, /* src_mask */
3222159047fSniklas 0x3fffffc, /* dst_mask */
323c074d1c9Sdrahn FALSE), /* pcrel_offset */
3242159047fSniklas
3252159047fSniklas { 9 },
3262159047fSniklas
3272159047fSniklas /* Non modifiable relative branch. */
3282159047fSniklas HOWTO (0xa, /* type */
3292159047fSniklas 0, /* rightshift */
3302159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
3312159047fSniklas 26, /* bitsize */
332c074d1c9Sdrahn TRUE, /* pc_relative */
3332159047fSniklas 0, /* bitpos */
3342159047fSniklas complain_overflow_signed, /* complain_on_overflow */
3352159047fSniklas 0, /* special_function */
3362159047fSniklas "R_BR", /* name */
337c074d1c9Sdrahn TRUE, /* partial_inplace */
3382159047fSniklas 0x3fffffc, /* src_mask */
3392159047fSniklas 0x3fffffc, /* dst_mask */
340c074d1c9Sdrahn FALSE), /* pcrel_offset */
3412159047fSniklas
3422159047fSniklas { 0xb },
3432159047fSniklas
3442159047fSniklas /* Indirect load. */
3452159047fSniklas HOWTO (0xc, /* type */
3462159047fSniklas 0, /* rightshift */
3472159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
3482159047fSniklas 16, /* bitsize */
349c074d1c9Sdrahn FALSE, /* pc_relative */
3502159047fSniklas 0, /* bitpos */
3512159047fSniklas complain_overflow_bitfield, /* complain_on_overflow */
3522159047fSniklas 0, /* special_function */
3532159047fSniklas "R_RL", /* name */
354c074d1c9Sdrahn TRUE, /* partial_inplace */
3552159047fSniklas 0xffff, /* src_mask */
3562159047fSniklas 0xffff, /* dst_mask */
357c074d1c9Sdrahn FALSE), /* pcrel_offset */
3582159047fSniklas
3592159047fSniklas /* Load address. */
3602159047fSniklas HOWTO (0xd, /* type */
3612159047fSniklas 0, /* rightshift */
3622159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
3632159047fSniklas 16, /* bitsize */
364c074d1c9Sdrahn FALSE, /* pc_relative */
3652159047fSniklas 0, /* bitpos */
3662159047fSniklas complain_overflow_bitfield, /* complain_on_overflow */
3672159047fSniklas 0, /* special_function */
3682159047fSniklas "R_RLA", /* name */
369c074d1c9Sdrahn TRUE, /* partial_inplace */
3702159047fSniklas 0xffff, /* src_mask */
3712159047fSniklas 0xffff, /* dst_mask */
372c074d1c9Sdrahn FALSE), /* pcrel_offset */
3732159047fSniklas
3742159047fSniklas { 0xe },
3752159047fSniklas
3762159047fSniklas /* Non-relocating reference. */
3772159047fSniklas HOWTO (0xf, /* type */
3782159047fSniklas 0, /* rightshift */
3792159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
3802159047fSniklas 32, /* bitsize */
381c074d1c9Sdrahn FALSE, /* pc_relative */
3822159047fSniklas 0, /* bitpos */
3832159047fSniklas complain_overflow_bitfield, /* complain_on_overflow */
3842159047fSniklas 0, /* special_function */
3852159047fSniklas "R_REF", /* name */
386c074d1c9Sdrahn FALSE, /* partial_inplace */
3872159047fSniklas 0, /* src_mask */
3882159047fSniklas 0, /* dst_mask */
389c074d1c9Sdrahn FALSE), /* pcrel_offset */
3902159047fSniklas
3912159047fSniklas { 0x10 },
3922159047fSniklas { 0x11 },
3932159047fSniklas
3942159047fSniklas /* TOC relative indirect load. */
3952159047fSniklas HOWTO (0x12, /* type */
3962159047fSniklas 0, /* rightshift */
3972159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
3982159047fSniklas 16, /* bitsize */
399c074d1c9Sdrahn FALSE, /* pc_relative */
4002159047fSniklas 0, /* bitpos */
4012159047fSniklas complain_overflow_bitfield, /* complain_on_overflow */
4022159047fSniklas 0, /* special_function */
4032159047fSniklas "R_TRL", /* name */
404c074d1c9Sdrahn TRUE, /* partial_inplace */
4052159047fSniklas 0xffff, /* src_mask */
4062159047fSniklas 0xffff, /* dst_mask */
407c074d1c9Sdrahn FALSE), /* pcrel_offset */
4082159047fSniklas
4092159047fSniklas /* TOC relative load address. */
4102159047fSniklas HOWTO (0x13, /* type */
4112159047fSniklas 0, /* rightshift */
4122159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
4132159047fSniklas 16, /* bitsize */
414c074d1c9Sdrahn FALSE, /* pc_relative */
4152159047fSniklas 0, /* bitpos */
4162159047fSniklas complain_overflow_bitfield, /* complain_on_overflow */
4172159047fSniklas 0, /* special_function */
4182159047fSniklas "R_TRLA", /* name */
419c074d1c9Sdrahn TRUE, /* partial_inplace */
4202159047fSniklas 0xffff, /* src_mask */
4212159047fSniklas 0xffff, /* dst_mask */
422c074d1c9Sdrahn FALSE), /* pcrel_offset */
4232159047fSniklas
4242159047fSniklas /* Modifiable relative branch. */
4252159047fSniklas HOWTO (0x14, /* type */
4262159047fSniklas 1, /* rightshift */
4272159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
4282159047fSniklas 32, /* bitsize */
429c074d1c9Sdrahn FALSE, /* pc_relative */
4302159047fSniklas 0, /* bitpos */
4312159047fSniklas complain_overflow_bitfield, /* complain_on_overflow */
4322159047fSniklas 0, /* special_function */
4332159047fSniklas "R_RRTBI", /* name */
434c074d1c9Sdrahn TRUE, /* partial_inplace */
4352159047fSniklas 0xffffffff, /* src_mask */
4362159047fSniklas 0xffffffff, /* dst_mask */
437c074d1c9Sdrahn FALSE), /* pcrel_offset */
4382159047fSniklas
4392159047fSniklas /* Modifiable absolute branch. */
4402159047fSniklas HOWTO (0x15, /* type */
4412159047fSniklas 1, /* rightshift */
4422159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
4432159047fSniklas 32, /* bitsize */
444c074d1c9Sdrahn FALSE, /* pc_relative */
4452159047fSniklas 0, /* bitpos */
4462159047fSniklas complain_overflow_bitfield, /* complain_on_overflow */
4472159047fSniklas 0, /* special_function */
4482159047fSniklas "R_RRTBA", /* name */
449c074d1c9Sdrahn TRUE, /* partial_inplace */
4502159047fSniklas 0xffffffff, /* src_mask */
4512159047fSniklas 0xffffffff, /* dst_mask */
452c074d1c9Sdrahn FALSE), /* pcrel_offset */
4532159047fSniklas
4542159047fSniklas /* Modifiable call absolute indirect. */
4552159047fSniklas HOWTO (0x16, /* type */
4562159047fSniklas 0, /* rightshift */
4572159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
4582159047fSniklas 16, /* bitsize */
459c074d1c9Sdrahn FALSE, /* pc_relative */
4602159047fSniklas 0, /* bitpos */
4612159047fSniklas complain_overflow_bitfield, /* complain_on_overflow */
4622159047fSniklas 0, /* special_function */
4632159047fSniklas "R_CAI", /* name */
464c074d1c9Sdrahn TRUE, /* partial_inplace */
4652159047fSniklas 0xffff, /* src_mask */
4662159047fSniklas 0xffff, /* dst_mask */
467c074d1c9Sdrahn FALSE), /* pcrel_offset */
4682159047fSniklas
4692159047fSniklas /* Modifiable call relative. */
4702159047fSniklas HOWTO (0x17, /* type */
4712159047fSniklas 0, /* rightshift */
4722159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
4732159047fSniklas 16, /* bitsize */
474c074d1c9Sdrahn FALSE, /* pc_relative */
4752159047fSniklas 0, /* bitpos */
4762159047fSniklas complain_overflow_bitfield, /* complain_on_overflow */
4772159047fSniklas 0, /* special_function */
4782159047fSniklas "R_REL", /* name */
479c074d1c9Sdrahn TRUE, /* partial_inplace */
4802159047fSniklas 0xffff, /* src_mask */
4812159047fSniklas 0xffff, /* dst_mask */
482c074d1c9Sdrahn FALSE), /* pcrel_offset */
4832159047fSniklas
4842159047fSniklas /* Modifiable branch absolute. */
4852159047fSniklas HOWTO (0x18, /* type */
4862159047fSniklas 0, /* rightshift */
4872159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
4882159047fSniklas 16, /* bitsize */
489c074d1c9Sdrahn FALSE, /* pc_relative */
4902159047fSniklas 0, /* bitpos */
4912159047fSniklas complain_overflow_bitfield, /* complain_on_overflow */
4922159047fSniklas 0, /* special_function */
4932159047fSniklas "R_RBA", /* name */
494c074d1c9Sdrahn TRUE, /* partial_inplace */
4952159047fSniklas 0xffff, /* src_mask */
4962159047fSniklas 0xffff, /* dst_mask */
497c074d1c9Sdrahn FALSE), /* pcrel_offset */
4982159047fSniklas
4992159047fSniklas /* Modifiable branch absolute. */
5002159047fSniklas HOWTO (0x19, /* type */
5012159047fSniklas 0, /* rightshift */
5022159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
5032159047fSniklas 16, /* bitsize */
504c074d1c9Sdrahn FALSE, /* pc_relative */
5052159047fSniklas 0, /* bitpos */
5062159047fSniklas complain_overflow_bitfield, /* complain_on_overflow */
5072159047fSniklas 0, /* special_function */
5082159047fSniklas "R_RBAC", /* name */
509c074d1c9Sdrahn TRUE, /* partial_inplace */
5102159047fSniklas 0xffff, /* src_mask */
5112159047fSniklas 0xffff, /* dst_mask */
512c074d1c9Sdrahn FALSE), /* pcrel_offset */
5132159047fSniklas
5142159047fSniklas /* Modifiable branch relative. */
5152159047fSniklas HOWTO (0x1a, /* type */
5162159047fSniklas 0, /* rightshift */
5172159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
5182159047fSniklas 26, /* bitsize */
519c074d1c9Sdrahn FALSE, /* pc_relative */
5202159047fSniklas 0, /* bitpos */
5212159047fSniklas complain_overflow_signed, /* complain_on_overflow */
5222159047fSniklas 0, /* special_function */
5232159047fSniklas "R_REL", /* name */
524c074d1c9Sdrahn TRUE, /* partial_inplace */
5252159047fSniklas 0xffff, /* src_mask */
5262159047fSniklas 0xffff, /* dst_mask */
527c074d1c9Sdrahn FALSE), /* pcrel_offset */
5282159047fSniklas
5292159047fSniklas /* Modifiable branch absolute. */
5302159047fSniklas HOWTO (0x1b, /* type */
5312159047fSniklas 0, /* rightshift */
5322159047fSniklas 2, /* size (0 = byte, 1 = short, 2 = long) */
5332159047fSniklas 16, /* bitsize */
534c074d1c9Sdrahn FALSE, /* pc_relative */
5352159047fSniklas 0, /* bitpos */
5362159047fSniklas complain_overflow_bitfield, /* complain_on_overflow */
5372159047fSniklas 0, /* special_function */
5382159047fSniklas "R_REL", /* name */
539c074d1c9Sdrahn TRUE, /* partial_inplace */
5402159047fSniklas 0xffff, /* src_mask */
5412159047fSniklas 0xffff, /* dst_mask */
542c074d1c9Sdrahn FALSE) /* pcrel_offset */
5432159047fSniklas };
5442159047fSniklas
5452159047fSniklas #define HOWTO_COUNT (sizeof nlm_powerpc_howto_table \
5462159047fSniklas / sizeof nlm_powerpc_howto_table[0])
5472159047fSniklas
5482159047fSniklas /* Read a PowerPC NLM reloc. */
5492159047fSniklas
550c074d1c9Sdrahn static bfd_boolean
nlm_powerpc_read_reloc(abfd,sym,secp,rel)5512159047fSniklas nlm_powerpc_read_reloc (abfd, sym, secp, rel)
5522159047fSniklas bfd *abfd;
5532159047fSniklas nlmNAME(symbol_type) *sym;
5542159047fSniklas asection **secp;
5552159047fSniklas arelent *rel;
5562159047fSniklas {
5572159047fSniklas struct nlm32_powerpc_external_reloc ext;
5582159047fSniklas bfd_vma l_vaddr;
5592159047fSniklas unsigned long l_symndx;
5602159047fSniklas int l_rtype;
5612159047fSniklas int l_rsecnm;
5622159047fSniklas asection *code_sec, *data_sec, *bss_sec;
5632159047fSniklas
5642159047fSniklas /* Read the reloc from the file. */
565c074d1c9Sdrahn if (bfd_bread (&ext, (bfd_size_type) sizeof ext, abfd) != sizeof ext)
566c074d1c9Sdrahn return FALSE;
5672159047fSniklas
5682159047fSniklas /* Swap in the fields. */
569c074d1c9Sdrahn l_vaddr = H_GET_32 (abfd, ext.l_vaddr);
570c074d1c9Sdrahn l_symndx = H_GET_32 (abfd, ext.l_symndx);
571c074d1c9Sdrahn l_rtype = H_GET_16 (abfd, ext.l_rtype);
572c074d1c9Sdrahn l_rsecnm = H_GET_16 (abfd, ext.l_rsecnm);
5732159047fSniklas
5742159047fSniklas /* Get the sections now, for convenience. */
5752159047fSniklas code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
5762159047fSniklas data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
5772159047fSniklas bss_sec = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
5782159047fSniklas
5792159047fSniklas /* Work out the arelent fields. */
5802159047fSniklas if (sym != NULL)
5812159047fSniklas {
5822159047fSniklas /* This is an import. sym_ptr_ptr is filled in by
5832159047fSniklas nlm_canonicalize_reloc. */
5842159047fSniklas rel->sym_ptr_ptr = NULL;
5852159047fSniklas }
5862159047fSniklas else
5872159047fSniklas {
5882159047fSniklas asection *sec;
5892159047fSniklas
5902159047fSniklas if (l_symndx == 0)
5912159047fSniklas sec = code_sec;
5922159047fSniklas else if (l_symndx == 1)
5932159047fSniklas sec = data_sec;
5942159047fSniklas else if (l_symndx == 2)
5952159047fSniklas sec = bss_sec;
5962159047fSniklas else
5972159047fSniklas {
5982159047fSniklas bfd_set_error (bfd_error_bad_value);
599c074d1c9Sdrahn return FALSE;
6002159047fSniklas }
6012159047fSniklas
6022159047fSniklas rel->sym_ptr_ptr = sec->symbol_ptr_ptr;
6032159047fSniklas }
6042159047fSniklas
6052159047fSniklas rel->addend = 0;
6062159047fSniklas
6072159047fSniklas BFD_ASSERT ((l_rtype & 0xff) < HOWTO_COUNT);
6082159047fSniklas
6092159047fSniklas rel->howto = nlm_powerpc_howto_table + (l_rtype & 0xff);
6102159047fSniklas
6112159047fSniklas BFD_ASSERT (rel->howto->name != NULL
6122159047fSniklas && ((l_rtype & 0x8000) != 0
6132159047fSniklas ? (rel->howto->complain_on_overflow
6142159047fSniklas == complain_overflow_signed)
6152159047fSniklas : (rel->howto->complain_on_overflow
6162159047fSniklas == complain_overflow_bitfield))
6172159047fSniklas && ((l_rtype >> 8) & 0x1f) == rel->howto->bitsize - 1);
6182159047fSniklas
6192159047fSniklas if (l_rsecnm == 0)
6202159047fSniklas *secp = code_sec;
6212159047fSniklas else if (l_rsecnm == 1)
6222159047fSniklas {
6232159047fSniklas *secp = data_sec;
6242159047fSniklas l_vaddr -= bfd_section_size (abfd, code_sec);
6252159047fSniklas }
6262159047fSniklas else
6272159047fSniklas {
6282159047fSniklas bfd_set_error (bfd_error_bad_value);
629c074d1c9Sdrahn return FALSE;
6302159047fSniklas }
6312159047fSniklas
6322159047fSniklas rel->address = l_vaddr;
6332159047fSniklas
634c074d1c9Sdrahn return TRUE;
6352159047fSniklas }
6362159047fSniklas
6372159047fSniklas #endif /* OLDFORMAT */
6382159047fSniklas
6392159047fSniklas /* Mangle PowerPC NLM relocs for output. */
6402159047fSniklas
641c074d1c9Sdrahn static bfd_boolean
nlm_powerpc_mangle_relocs(abfd,sec,data,offset,count)6422159047fSniklas nlm_powerpc_mangle_relocs (abfd, sec, data, offset, count)
643b305b0f1Sespie bfd *abfd ATTRIBUTE_UNUSED;
644b305b0f1Sespie asection *sec ATTRIBUTE_UNUSED;
645*007c2a45Smiod const PTR data ATTRIBUTE_UNUSED;
646b305b0f1Sespie bfd_vma offset ATTRIBUTE_UNUSED;
647b305b0f1Sespie bfd_size_type count ATTRIBUTE_UNUSED;
6482159047fSniklas {
649c074d1c9Sdrahn return TRUE;
6502159047fSniklas }
6512159047fSniklas
6522159047fSniklas /* Read a PowerPC NLM import record */
6532159047fSniklas
654c074d1c9Sdrahn static bfd_boolean
nlm_powerpc_read_import(abfd,sym)6552159047fSniklas nlm_powerpc_read_import (abfd, sym)
6562159047fSniklas bfd *abfd;
6572159047fSniklas nlmNAME(symbol_type) *sym;
6582159047fSniklas {
6592159047fSniklas struct nlm_relent *nlm_relocs; /* relocation records for symbol */
6602159047fSniklas bfd_size_type rcount; /* number of relocs */
6612159047fSniklas bfd_byte temp[NLM_TARGET_LONG_SIZE]; /* temporary 32-bit value */
6622159047fSniklas unsigned char symlength; /* length of symbol name */
6632159047fSniklas char *name;
6642159047fSniklas
665c074d1c9Sdrahn if (bfd_bread ((PTR) &symlength, (bfd_size_type) sizeof (symlength), abfd)
6662159047fSniklas != sizeof (symlength))
667c074d1c9Sdrahn return FALSE;
6682159047fSniklas sym -> symbol.the_bfd = abfd;
669c074d1c9Sdrahn name = bfd_alloc (abfd, (bfd_size_type) symlength + 1);
6702159047fSniklas if (name == NULL)
671c074d1c9Sdrahn return FALSE;
672c074d1c9Sdrahn if (bfd_bread (name, (bfd_size_type) symlength, abfd) != symlength)
673c074d1c9Sdrahn return FALSE;
6742159047fSniklas name[symlength] = '\0';
6752159047fSniklas sym -> symbol.name = name;
6762159047fSniklas sym -> symbol.flags = 0;
6772159047fSniklas sym -> symbol.value = 0;
6782159047fSniklas sym -> symbol.section = bfd_und_section_ptr;
679c074d1c9Sdrahn if (bfd_bread ((PTR) temp, (bfd_size_type) sizeof (temp), abfd)
680c074d1c9Sdrahn != sizeof (temp))
681c074d1c9Sdrahn return FALSE;
682c074d1c9Sdrahn rcount = H_GET_32 (abfd, temp);
6832159047fSniklas nlm_relocs = ((struct nlm_relent *)
6842159047fSniklas bfd_alloc (abfd, rcount * sizeof (struct nlm_relent)));
6852159047fSniklas if (nlm_relocs == (struct nlm_relent *) NULL)
686c074d1c9Sdrahn return FALSE;
6872159047fSniklas sym -> relocs = nlm_relocs;
6882159047fSniklas sym -> rcnt = 0;
6892159047fSniklas while (sym -> rcnt < rcount)
6902159047fSniklas {
6912159047fSniklas asection *section;
6922159047fSniklas
693c074d1c9Sdrahn if (! nlm_powerpc_read_reloc (abfd, sym, §ion, &nlm_relocs -> reloc))
694c074d1c9Sdrahn return FALSE;
6952159047fSniklas nlm_relocs -> section = section;
6962159047fSniklas nlm_relocs++;
6972159047fSniklas sym -> rcnt++;
6982159047fSniklas }
699c074d1c9Sdrahn return TRUE;
7002159047fSniklas }
7012159047fSniklas
7022159047fSniklas #ifndef OLDFORMAT
7032159047fSniklas
7042159047fSniklas /* Write a PowerPC NLM reloc. */
7052159047fSniklas
706c074d1c9Sdrahn static bfd_boolean
nlm_powerpc_write_import(abfd,sec,rel)7072159047fSniklas nlm_powerpc_write_import (abfd, sec, rel)
7082159047fSniklas bfd *abfd;
7092159047fSniklas asection *sec;
7102159047fSniklas arelent *rel;
7112159047fSniklas {
7122159047fSniklas asymbol *sym;
7132159047fSniklas bfd_vma val;
7142159047fSniklas bfd_byte temp[4];
7152159047fSniklas
7162159047fSniklas /* PowerPC NetWare only supports one kind of reloc. */
7172159047fSniklas if (rel->addend != 0
7182159047fSniklas || rel->howto == NULL
7192159047fSniklas || rel->howto->rightshift != 0
7202159047fSniklas || rel->howto->size != 2
7212159047fSniklas || rel->howto->bitsize != 32
7222159047fSniklas || rel->howto->bitpos != 0
7232159047fSniklas || rel->howto->pc_relative
7242159047fSniklas || (rel->howto->src_mask != 0xffffffff && rel->addend != 0)
7252159047fSniklas || rel->howto->dst_mask != 0xffffffff)
7262159047fSniklas {
7272159047fSniklas bfd_set_error (bfd_error_invalid_operation);
728c074d1c9Sdrahn return FALSE;
7292159047fSniklas }
7302159047fSniklas
7312159047fSniklas sym = *rel->sym_ptr_ptr;
7322159047fSniklas
7332159047fSniklas /* The value we write out is the offset into the appropriate
7342159047fSniklas segment, rightshifted by two. This offset is the section vma,
7352159047fSniklas adjusted by the vma of the lowest section in that segment, plus
7362159047fSniklas the address of the relocation. */
7372159047fSniklas val = bfd_get_section_vma (abfd, sec) + rel->address;
7382159047fSniklas if ((val & 3) != 0)
7392159047fSniklas {
7402159047fSniklas bfd_set_error (bfd_error_bad_value);
741c074d1c9Sdrahn return FALSE;
7422159047fSniklas }
7432159047fSniklas val >>= 2;
7442159047fSniklas
7452159047fSniklas /* The high bit is 0 if the reloc is in the data section, or 1 if
7462159047fSniklas the reloc is in the code section. */
7472159047fSniklas if (bfd_get_section_flags (abfd, sec) & SEC_DATA)
7482159047fSniklas val -= nlm_get_data_low (abfd);
7492159047fSniklas else
7502159047fSniklas {
7512159047fSniklas val -= nlm_get_text_low (abfd);
7522159047fSniklas val |= NLM_HIBIT;
7532159047fSniklas }
7542159047fSniklas
7552159047fSniklas if (! bfd_is_und_section (bfd_get_section (sym)))
7562159047fSniklas {
7572159047fSniklas /* This is an internal relocation fixup. The second most
7582159047fSniklas significant bit is 0 if this is a reloc against the data
7592159047fSniklas segment, or 1 if it is a reloc against the text segment. */
7602159047fSniklas if (bfd_get_section_flags (abfd, bfd_get_section (sym)) & SEC_CODE)
7612159047fSniklas val |= NLM_HIBIT >> 1;
7622159047fSniklas }
7632159047fSniklas
7642159047fSniklas bfd_put_32 (abfd, val, temp);
765c074d1c9Sdrahn if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp))
766c074d1c9Sdrahn return FALSE;
7672159047fSniklas
768c074d1c9Sdrahn return TRUE;
7692159047fSniklas }
7702159047fSniklas
7712159047fSniklas #else /* OLDFORMAT */
7722159047fSniklas
7732159047fSniklas /* This is used for the reloc handling in the old format. */
7742159047fSniklas
7752159047fSniklas /* Write a PowerPC NLM reloc. */
7762159047fSniklas
777c074d1c9Sdrahn static bfd_boolean
nlm_powerpc_write_reloc(abfd,sec,rel,indx)7782159047fSniklas nlm_powerpc_write_reloc (abfd, sec, rel, indx)
7792159047fSniklas bfd *abfd;
7802159047fSniklas asection *sec;
7812159047fSniklas arelent *rel;
7822159047fSniklas int indx;
7832159047fSniklas {
7842159047fSniklas struct nlm32_powerpc_external_reloc ext;
7852159047fSniklas asection *code_sec, *data_sec, *bss_sec;
7862159047fSniklas asymbol *sym;
7872159047fSniklas asection *symsec;
7882159047fSniklas unsigned long l_symndx;
7892159047fSniklas int l_rtype;
7902159047fSniklas int l_rsecnm;
7912159047fSniklas reloc_howto_type *howto;
7922159047fSniklas bfd_size_type address;
7932159047fSniklas
7942159047fSniklas /* Get the sections now, for convenience. */
7952159047fSniklas code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
7962159047fSniklas data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
7972159047fSniklas bss_sec = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
7982159047fSniklas
7992159047fSniklas sym = *rel->sym_ptr_ptr;
8002159047fSniklas symsec = bfd_get_section (sym);
8012159047fSniklas if (indx != -1)
8022159047fSniklas {
8032159047fSniklas BFD_ASSERT (bfd_is_und_section (symsec));
8042159047fSniklas l_symndx = indx + 3;
8052159047fSniklas }
8062159047fSniklas else
8072159047fSniklas {
8082159047fSniklas if (symsec == code_sec)
8092159047fSniklas l_symndx = 0;
8102159047fSniklas else if (symsec == data_sec)
8112159047fSniklas l_symndx = 1;
8122159047fSniklas else if (symsec == bss_sec)
8132159047fSniklas l_symndx = 2;
8142159047fSniklas else
8152159047fSniklas {
8162159047fSniklas bfd_set_error (bfd_error_bad_value);
817c074d1c9Sdrahn return FALSE;
8182159047fSniklas }
8192159047fSniklas }
8202159047fSniklas
821c074d1c9Sdrahn H_PUT_32 (abfd, l_symndx, ext.l_symndx);
8222159047fSniklas
8232159047fSniklas for (howto = nlm_powerpc_howto_table;
8242159047fSniklas howto < nlm_powerpc_howto_table + HOWTO_COUNT;
8252159047fSniklas howto++)
8262159047fSniklas {
8272159047fSniklas if (howto->rightshift == rel->howto->rightshift
8282159047fSniklas && howto->size == rel->howto->size
8292159047fSniklas && howto->bitsize == rel->howto->bitsize
8302159047fSniklas && howto->pc_relative == rel->howto->pc_relative
8312159047fSniklas && howto->bitpos == rel->howto->bitpos
8322159047fSniklas && (howto->partial_inplace == rel->howto->partial_inplace
8332159047fSniklas || (! rel->howto->partial_inplace
8342159047fSniklas && rel->addend == 0))
8352159047fSniklas && (howto->src_mask == rel->howto->src_mask
8362159047fSniklas || (rel->howto->src_mask == 0
8372159047fSniklas && rel->addend == 0))
8382159047fSniklas && howto->dst_mask == rel->howto->dst_mask
8392159047fSniklas && howto->pcrel_offset == rel->howto->pcrel_offset)
8402159047fSniklas break;
8412159047fSniklas }
8422159047fSniklas if (howto >= nlm_powerpc_howto_table + HOWTO_COUNT)
8432159047fSniklas {
8442159047fSniklas bfd_set_error (bfd_error_bad_value);
845c074d1c9Sdrahn return FALSE;
8462159047fSniklas }
8472159047fSniklas
8482159047fSniklas l_rtype = howto->type;
8492159047fSniklas if (howto->complain_on_overflow == complain_overflow_signed)
8502159047fSniklas l_rtype |= 0x8000;
8512159047fSniklas l_rtype |= (howto->bitsize - 1) << 8;
852c074d1c9Sdrahn H_PUT_16 (abfd, l_rtype, ext.l_rtype);
8532159047fSniklas
8542159047fSniklas address = rel->address;
8552159047fSniklas
8562159047fSniklas if (sec == code_sec)
8572159047fSniklas l_rsecnm = 0;
8582159047fSniklas else if (sec == data_sec)
8592159047fSniklas {
8602159047fSniklas l_rsecnm = 1;
8612159047fSniklas address += bfd_section_size (abfd, code_sec);
8622159047fSniklas }
8632159047fSniklas else
8642159047fSniklas {
8652159047fSniklas bfd_set_error (bfd_error_bad_value);
866c074d1c9Sdrahn return FALSE;
8672159047fSniklas }
8682159047fSniklas
869c074d1c9Sdrahn H_PUT_16 (abfd, l_rsecnm, ext.l_rsecnm);
870c074d1c9Sdrahn H_PUT_32 (abfd, address, ext.l_vaddr);
8712159047fSniklas
872c074d1c9Sdrahn if (bfd_bwrite (&ext, (bfd_size_type) sizeof ext, abfd) != sizeof ext)
873c074d1c9Sdrahn return FALSE;
8742159047fSniklas
875c074d1c9Sdrahn return TRUE;
8762159047fSniklas }
8772159047fSniklas
8782159047fSniklas /* Write a PowerPC NLM import. */
8792159047fSniklas
880c074d1c9Sdrahn static bfd_boolean
nlm_powerpc_write_import(abfd,sec,rel)8812159047fSniklas nlm_powerpc_write_import (abfd, sec, rel)
8822159047fSniklas bfd *abfd;
8832159047fSniklas asection *sec;
8842159047fSniklas arelent *rel;
8852159047fSniklas {
8862159047fSniklas return nlm_powerpc_write_reloc (abfd, sec, rel, -1);
8872159047fSniklas }
8882159047fSniklas
8892159047fSniklas #endif /* OLDFORMAT */
8902159047fSniklas
8912159047fSniklas /* Write a PowerPC NLM external symbol. This routine keeps a static
8922159047fSniklas count of the symbol index. FIXME: I don't know if this is
8932159047fSniklas necessary, and the index never gets reset. */
8942159047fSniklas
895c074d1c9Sdrahn static bfd_boolean
nlm_powerpc_write_external(abfd,count,sym,relocs)8962159047fSniklas nlm_powerpc_write_external (abfd, count, sym, relocs)
8972159047fSniklas bfd *abfd;
8982159047fSniklas bfd_size_type count;
8992159047fSniklas asymbol *sym;
9002159047fSniklas struct reloc_and_sec *relocs;
9012159047fSniklas {
9022159047fSniklas unsigned int i;
9032159047fSniklas bfd_byte len;
9042159047fSniklas unsigned char temp[NLM_TARGET_LONG_SIZE];
9052159047fSniklas #ifdef OLDFORMAT
9062159047fSniklas static int indx;
9072159047fSniklas #endif
9082159047fSniklas
9092159047fSniklas len = strlen (sym->name);
910c074d1c9Sdrahn if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd)
911c074d1c9Sdrahn != sizeof (bfd_byte))
912c074d1c9Sdrahn || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len)
913c074d1c9Sdrahn return FALSE;
9142159047fSniklas
9152159047fSniklas bfd_put_32 (abfd, count, temp);
916c074d1c9Sdrahn if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp))
917c074d1c9Sdrahn return FALSE;
9182159047fSniklas
9192159047fSniklas for (i = 0; i < count; i++)
9202159047fSniklas {
9212159047fSniklas #ifndef OLDFORMAT
9222159047fSniklas if (! nlm_powerpc_write_import (abfd, relocs[i].sec, relocs[i].rel))
923c074d1c9Sdrahn return FALSE;
9242159047fSniklas #else
9252159047fSniklas if (! nlm_powerpc_write_reloc (abfd, relocs[i].sec,
9262159047fSniklas relocs[i].rel, indx))
927c074d1c9Sdrahn return FALSE;
9282159047fSniklas #endif
9292159047fSniklas }
9302159047fSniklas
9312159047fSniklas #ifdef OLDFORMAT
9322159047fSniklas ++indx;
9332159047fSniklas #endif
9342159047fSniklas
935c074d1c9Sdrahn return TRUE;
9362159047fSniklas }
9372159047fSniklas
9382159047fSniklas #ifndef OLDFORMAT
9392159047fSniklas
9402159047fSniklas /* PowerPC Netware uses a word offset, not a byte offset, for public
9412159047fSniklas symbols. */
9422159047fSniklas
9432159047fSniklas /* Set the section for a public symbol. */
9442159047fSniklas
945c074d1c9Sdrahn static bfd_boolean
nlm_powerpc_set_public_section(abfd,sym)9462159047fSniklas nlm_powerpc_set_public_section (abfd, sym)
9472159047fSniklas bfd *abfd;
9482159047fSniklas nlmNAME(symbol_type) *sym;
9492159047fSniklas {
9502159047fSniklas if (sym->symbol.value & NLM_HIBIT)
9512159047fSniklas {
9522159047fSniklas sym->symbol.value &= ~NLM_HIBIT;
9532159047fSniklas sym->symbol.flags |= BSF_FUNCTION;
9542159047fSniklas sym->symbol.section =
9552159047fSniklas bfd_get_section_by_name (abfd, NLM_CODE_NAME);
9562159047fSniklas }
9572159047fSniklas else
9582159047fSniklas {
9592159047fSniklas sym->symbol.section =
9602159047fSniklas bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
9612159047fSniklas }
9622159047fSniklas
9632159047fSniklas sym->symbol.value <<= 2;
9642159047fSniklas
965c074d1c9Sdrahn return TRUE;
9662159047fSniklas }
9672159047fSniklas
9682159047fSniklas /* Get the offset to write out for a public symbol. */
9692159047fSniklas
9702159047fSniklas static bfd_vma
nlm_powerpc_get_public_offset(abfd,sym)9712159047fSniklas nlm_powerpc_get_public_offset (abfd, sym)
9722159047fSniklas bfd *abfd;
9732159047fSniklas asymbol *sym;
9742159047fSniklas {
9752159047fSniklas bfd_vma offset;
9762159047fSniklas asection *sec;
9772159047fSniklas
9782159047fSniklas offset = bfd_asymbol_value (sym);
9792159047fSniklas sec = bfd_get_section (sym);
9802159047fSniklas if (sec->flags & SEC_CODE)
9812159047fSniklas {
9822159047fSniklas offset -= nlm_get_text_low (abfd);
9832159047fSniklas offset |= NLM_HIBIT;
9842159047fSniklas }
9852159047fSniklas else if (sec->flags & (SEC_DATA | SEC_ALLOC))
9862159047fSniklas {
9872159047fSniklas /* SEC_ALLOC is for the .bss section. */
9882159047fSniklas offset -= nlm_get_data_low (abfd);
9892159047fSniklas }
9902159047fSniklas else
9912159047fSniklas {
9922159047fSniklas /* We can't handle an exported symbol that is not in the code or
9932159047fSniklas data segment. */
9942159047fSniklas bfd_set_error (bfd_error_invalid_operation);
9952159047fSniklas /* FIXME: No way to return error. */
9962159047fSniklas abort ();
9972159047fSniklas }
9982159047fSniklas
9992159047fSniklas return offset;
10002159047fSniklas }
10012159047fSniklas
10022159047fSniklas #endif /* ! defined (OLDFORMAT) */
10032159047fSniklas
10042159047fSniklas #include "nlmswap.h"
10052159047fSniklas
10062159047fSniklas static const struct nlm_backend_data nlm32_powerpc_backend =
10072159047fSniklas {
10082159047fSniklas "NetWare PowerPC Module \032",
10092159047fSniklas sizeof (Nlm32_powerpc_External_Fixed_Header),
10102159047fSniklas #ifndef OLDFORMAT
10112159047fSniklas 0, /* optional_prefix_size */
10122159047fSniklas #else
10132159047fSniklas sizeof (struct nlm32_powerpc_external_prefix_header),
10142159047fSniklas #endif
10152159047fSniklas bfd_arch_powerpc,
10162159047fSniklas 0,
1017c074d1c9Sdrahn FALSE,
10182159047fSniklas #ifndef OLDFORMAT
10192159047fSniklas 0, /* backend_object_p */
10202159047fSniklas 0, /* write_prefix */
10212159047fSniklas #else
10222159047fSniklas nlm_powerpc_backend_object_p,
10232159047fSniklas nlm_powerpc_write_prefix,
10242159047fSniklas #endif
10252159047fSniklas nlm_powerpc_read_reloc,
10262159047fSniklas nlm_powerpc_mangle_relocs,
10272159047fSniklas nlm_powerpc_read_import,
10282159047fSniklas nlm_powerpc_write_import,
10292159047fSniklas #ifndef OLDFORMAT
10302159047fSniklas nlm_powerpc_set_public_section,
10312159047fSniklas nlm_powerpc_get_public_offset,
10322159047fSniklas #else
10332159047fSniklas 0, /* set_public_section */
10342159047fSniklas 0, /* get_public_offset */
10352159047fSniklas #endif
10362159047fSniklas nlm_swap_fixed_header_in,
10372159047fSniklas nlm_swap_fixed_header_out,
10382159047fSniklas nlm_powerpc_write_external,
10392159047fSniklas 0, /* write_export */
10402159047fSniklas };
10412159047fSniklas
10422159047fSniklas #define TARGET_BIG_NAME "nlm32-powerpc"
10432159047fSniklas #define TARGET_BIG_SYM nlmNAME(powerpc_vec)
10442159047fSniklas #define TARGET_BACKEND_DATA &nlm32_powerpc_backend
10452159047fSniklas
10462159047fSniklas #include "nlm-target.h"
1047