Support for PowerPC ELF and PowerPC NetWare. Sanitization to follow.

This commit is contained in:
Ian Lance Taylor 1994-02-18 15:37:20 +00:00
parent 70126bf94e
commit d03d5626e5
2 changed files with 1020 additions and 0 deletions

281
bfd/elf32-powerpc.c Normal file
View File

@ -0,0 +1,281 @@
/* PowerPC-specific support for 32-bit ELF
Copyright 1994 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support.
This file is part of BFD, the Binary File Descriptor library.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* I wrote this file without the benefit of a PowerPC ELF ABI. Thus,
it probably does not correspond to whatever people finally settle
on. Ian Taylor. */
#include "bfd.h"
#include "sysdep.h"
#include "libbfd.h"
#include "libelf.h"
static bfd_reloc_status_type powerpc_elf_toc16_reloc PARAMS ((bfd *abfd,
arelent *reloc,
asymbol *symbol,
PTR data,
asection *sec,
bfd *output_bfd,
char **error));
static bfd_reloc_status_type powerpc_elf_b26_reloc PARAMS ((bfd *abfd,
arelent *reloc,
asymbol *symbol,
PTR data,
asection *sec,
bfd *output_bfd,
char **error));
static const struct reloc_howto_struct *bfd_elf32_bfd_reloc_type_lookup
PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
static void powerpc_info_to_howto_rel
PARAMS ((bfd *abfd, arelent *cache_ptr, Elf32_Internal_Rel *dst));
#define USE_REL
enum reloc_type
{
R_POWERPC_NONE = 0,
R_POWERPC_32,
R_POWERPC_B26,
R_POWERPC_BA26,
R_POWERPC_TOC16,
R_POWERPC_max
};
static reloc_howto_type elf_powerpc_howto_table[] =
{
/* This relocation does not do anything. */
HOWTO (R_POWERPC_NONE, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_POWERPC_NONE", /* name */
true, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
false), /* pcrel_offset */
/* Standard 32 bit relocation. */
HOWTO (R_POWERPC_32, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_POWERPC_32", /* name */
true, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
false), /* pcrel_offset */
/* 26 bit relative branch. */
HOWTO (R_POWERPC_B26, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
26, /* bitsize */
true, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
powerpc_elf_b26_reloc, /* special_function */
"R_POWERPC_B26", /* name */
true, /* partial_inplace */
0x3fffffc, /* src_mask */
0x3fffffc, /* dst_mask */
false), /* pcrel_offset */
/* 26 bit absolute branch. */
HOWTO (R_POWERPC_BA26, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
26, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_POWERPC_BA26", /* name */
true, /* partial_inplace */
0x3fffffc, /* src_mask */
0x3fffffc, /* dst_mask */
false), /* pcrel_offset */
/* 16 bit reference to TOC section. */
HOWTO (R_POWERPC_TOC16, /* type */
0, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
powerpc_elf_toc16_reloc, /* special_function */
"R_POWERPC_TOC16", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
false), /* pcrel_offset */
};
/* Handle the TOC16 reloc. We want to use the offset within the .toc
section, not the actual VMA. */
static bfd_reloc_status_type
powerpc_elf_toc16_reloc (abfd,
reloc_entry,
symbol,
data,
input_section,
output_bfd,
error_message)
bfd *abfd;
arelent *reloc_entry;
asymbol *symbol;
PTR data;
asection *input_section;
bfd *output_bfd;
char **error_message;
{
asection *sec;
/* Simply adjust the reloc addend by the negative of the VMA of the
.toc section. */
sec = bfd_get_section (*reloc_entry->sym_ptr_ptr);
if (sec == &bfd_und_section)
return bfd_reloc_continue;
BFD_ASSERT (strcmp (bfd_get_section_name (abfd, sec), ".toc") == 0);
reloc_entry->addend -= sec->output_section->vma;
return bfd_reloc_continue;
}
/* Handle a branch. If the next instruction is the special
instruction "cror 31,31,31", and this branch is to a stub routine
we have created, we must change the cror instruction into an
instruction which reloads the TOC register. We can detect a stub
routine because it is in a BFD named "linker stubs". FIXME: What a
hack. */
static bfd_reloc_status_type
powerpc_elf_b26_reloc (abfd,
reloc_entry,
symbol,
data,
input_section,
output_bfd,
error_message)
bfd *abfd;
arelent *reloc_entry;
asymbol *symbol;
PTR data;
asection *input_section;
bfd *output_bfd;
char **error_message;
{
if (bfd_get_section (symbol) != &bfd_und_section
&& (strcmp (bfd_get_section (symbol)->owner->filename, "linker stubs")
== 0))
{
bfd_vma val;
/* This symbol is a stub created by the linker. */
val = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address + 4);
if (val == 0x4ffffb82) /* cror 31,31,31 */
bfd_put_32 (abfd, (bfd_vma) 0x80410014, /* l r2,20(r1) */
(bfd_byte *) data + reloc_entry->address + 4);
}
if (output_bfd != (bfd *) NULL
&& bfd_get_section (symbol) == &bfd_und_section)
{
bfd_size_type address;
/* If we are generating relocateable output, and the symbol is
undefined, we just want to adjust the reloc by the amount the
section moved. */
address = reloc_entry->address;
reloc_entry->address += input_section->output_offset;
return _bfd_relocate_contents (reloc_entry->howto, abfd,
- input_section->output_offset,
(bfd_byte *) data + address);
}
/* Otherwise, let bfd_perform_relocation handle it. */
return bfd_reloc_continue;
}
/* Map BFD reloc types to PowerPC ELF reloc types. */
struct powerpc_reloc_map
{
unsigned char bfd_reloc_val;
unsigned char elf_reloc_val;
};
static const struct powerpc_reloc_map powerpc_reloc_map[] =
{
{ BFD_RELOC_NONE, R_POWERPC_NONE, },
{ BFD_RELOC_32, R_POWERPC_32 },
{ BFD_RELOC_CTOR, R_POWERPC_32 },
{ BFD_RELOC_PPC_B26, R_POWERPC_B26 },
{ BFD_RELOC_PPC_BA26, R_POWERPC_BA26 },
{ BFD_RELOC_PPC_TOC16, R_POWERPC_TOC16 }
};
static const struct reloc_howto_struct *
bfd_elf32_bfd_reloc_type_lookup (abfd, code)
bfd *abfd;
bfd_reloc_code_real_type code;
{
int i;
for (i = 0;
i < sizeof (powerpc_reloc_map) / sizeof (struct powerpc_reloc_map);
i++)
{
if (powerpc_reloc_map[i].bfd_reloc_val == code)
return &elf_powerpc_howto_table[powerpc_reloc_map[i].elf_reloc_val];
}
return NULL;
}
/* Set the howto pointer for a PowerPC ELF reloc. */
static void
powerpc_info_to_howto_rel (abfd, cache_ptr, dst)
bfd *abfd;
arelent *cache_ptr;
Elf32_Internal_Rel *dst;
{
BFD_ASSERT (ELF32_R_TYPE (dst->r_info) < (unsigned int) R_POWERPC_max);
cache_ptr->howto = &elf_powerpc_howto_table[ELF32_R_TYPE(dst->r_info)];
}
#define TARGET_BIG_SYM bfd_elf32_powerpc_vec
#define TARGET_BIG_NAME "elf32-powerpc"
#define ELF_ARCH bfd_arch_powerpc
#define ELF_MACHINE_CODE EM_CYGNUS_POWERPC
#define ELF_MAXPAGESIZE 0x10000
#define elf_info_to_howto 0
#define elf_info_to_howto_rel powerpc_info_to_howto_rel
#include "elf32-target.h"

739
bfd/nlm32-powerpc.c Normal file
View File

@ -0,0 +1,739 @@
/* Support for 32-bit PowerPC NLM (NetWare Loadable Module)
Copyright (C) 1994 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "bfd.h"
#include "sysdep.h"
#include "libbfd.h"
#define ARCH_SIZE 32
#include "nlm/ppc-ext.h"
#define Nlm_External_Fixed_Header Nlm32_powerpc_External_Fixed_Header
#include "libnlm.h"
static boolean nlm_powerpc_backend_object_p
PARAMS ((bfd *));
static boolean nlm_powerpc_write_prefix
PARAMS ((bfd *));
static boolean nlm_powerpc_read_reloc
PARAMS ((bfd *, nlmNAME(symbol_type) *, asection **, arelent *));
static boolean nlm_powerpc_mangle_relocs
PARAMS ((bfd *, asection *, PTR, bfd_vma, bfd_size_type));
static boolean nlm_powerpc_read_import
PARAMS ((bfd *, nlmNAME(symbol_type) *));
static boolean nlm_powerpc_write_import
PARAMS ((bfd *, asection *, arelent *));
static boolean nlm_powerpc_write_external
PARAMS ((bfd *, bfd_size_type, asymbol *, struct reloc_and_sec *));
/* PowerPC NLM's have a prefix header before the standard NLM. This
function reads it in, verifies the version, and seeks the bfd to
the location before the regular NLM header. */
static boolean
nlm_powerpc_backend_object_p (abfd)
bfd *abfd;
{
struct nlm32_powerpc_external_prefix_header s;
if (bfd_read ((PTR) &s, sizeof s, 1, abfd) != sizeof s)
return false;
if (memcmp (s.signature, NLM32_POWERPC_SIGNATURE, sizeof s.signature) != 0
|| bfd_h_get_32 (abfd, s.headerVersion) != NLM32_POWERPC_HEADER_VERSION)
return false;
return true;
}
/* Write out the prefix. */
static boolean
nlm_powerpc_write_prefix (abfd)
bfd *abfd;
{
struct nlm32_powerpc_external_prefix_header s;
memset (&s, 0, sizeof s);
memcpy (s.signature, NLM32_POWERPC_SIGNATURE, sizeof s.signature);
bfd_h_put_32 (abfd, (bfd_vma) NLM32_POWERPC_HEADER_VERSION, s.headerVersion);
bfd_h_put_32 (abfd, (bfd_vma) 0, s.origins);
/* FIXME: What should we do about the date? */
if (bfd_write ((PTR) &s, sizeof s, 1, abfd) != sizeof s)
return false;
return true;
}
/* How to process the various reloc types. PowerPC NLMs use XCOFF
reloc types, and I have just copied the XCOFF reloc table here. */
static reloc_howto_type nlm_powerpc_howto_table[] =
{
/* Standard 32 bit relocation. */
HOWTO (0, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
0, /* special_function */
"R_POS", /* name */
true, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
false), /* pcrel_offset */
/* 32 bit relocation, but store negative value. */
HOWTO (1, /* type */
0, /* rightshift */
-2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
0, /* special_function */
"R_NEG", /* name */
true, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
false), /* pcrel_offset */
/* 32 bit PC relative relocation. */
HOWTO (2, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
true, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
0, /* special_function */
"R_REL", /* name */
true, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
false), /* pcrel_offset */
/* 16 bit TOC relative relocation. */
HOWTO (3, /* type */
0, /* rightshift */
1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
0, /* special_function */
"R_TOC", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
false), /* pcrel_offset */
/* I don't really know what this is. */
HOWTO (4, /* type */
1, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
0, /* special_function */
"R_RTB", /* name */
true, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
false), /* pcrel_offset */
/* External TOC relative symbol. */
HOWTO (5, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
0, /* special_function */
"R_GL", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
false), /* pcrel_offset */
/* Local TOC relative symbol. */
HOWTO (6, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
0, /* special_function */
"R_TCL", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
false), /* pcrel_offset */
{ 7 },
/* Non modifiable absolute branch. */
HOWTO (8, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
26, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
0, /* special_function */
"R_BA", /* name */
true, /* partial_inplace */
0x3fffffc, /* src_mask */
0x3fffffc, /* dst_mask */
false), /* pcrel_offset */
{ 9 },
/* Non modifiable relative branch. */
HOWTO (0xa, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
26, /* bitsize */
true, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
0, /* special_function */
"R_BR", /* name */
true, /* partial_inplace */
0x3fffffc, /* src_mask */
0x3fffffc, /* dst_mask */
false), /* pcrel_offset */
{ 0xb },
/* Indirect load. */
HOWTO (0xc, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
0, /* special_function */
"R_RL", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
false), /* pcrel_offset */
/* Load address. */
HOWTO (0xd, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
0, /* special_function */
"R_RLA", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
false), /* pcrel_offset */
{ 0xe },
/* Non-relocating reference. */
HOWTO (0xf, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
0, /* special_function */
"R_REF", /* name */
false, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
false), /* pcrel_offset */
{ 0x10 },
{ 0x11 },
/* TOC relative indirect load. */
HOWTO (0x12, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
0, /* special_function */
"R_TRL", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
false), /* pcrel_offset */
/* TOC relative load address. */
HOWTO (0x13, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
0, /* special_function */
"R_TRLA", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
false), /* pcrel_offset */
/* Modifiable relative branch. */
HOWTO (0x14, /* type */
1, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
0, /* special_function */
"R_RRTBI", /* name */
true, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
false), /* pcrel_offset */
/* Modifiable absolute branch. */
HOWTO (0x15, /* type */
1, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
0, /* special_function */
"R_RRTBA", /* name */
true, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
false), /* pcrel_offset */
/* Modifiable call absolute indirect. */
HOWTO (0x16, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
0, /* special_function */
"R_CAI", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
false), /* pcrel_offset */
/* Modifiable call relative. */
HOWTO (0x17, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
0, /* special_function */
"R_REL", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
false), /* pcrel_offset */
/* Modifiable branch absolute. */
HOWTO (0x18, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
0, /* special_function */
"R_RBA", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
false), /* pcrel_offset */
/* Modifiable branch absolute. */
HOWTO (0x19, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
0, /* special_function */
"R_RBAC", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
false), /* pcrel_offset */
/* Modifiable branch relative. */
HOWTO (0x1a, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
26, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
0, /* special_function */
"R_REL", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
false), /* pcrel_offset */
/* Modifiable branch absolute. */
HOWTO (0x1b, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
0, /* special_function */
"R_REL", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
false) /* pcrel_offset */
};
#define HOWTO_COUNT (sizeof nlm_powerpc_howto_table \
/ sizeof nlm_powerpc_howto_table[0])
/* Read a PowerPC NLM reloc. */
static boolean
nlm_powerpc_read_reloc (abfd, sym, secp, rel)
bfd *abfd;
nlmNAME(symbol_type) *sym;
asection **secp;
arelent *rel;
{
struct nlm32_powerpc_external_reloc ext;
bfd_vma l_vaddr;
unsigned long l_symndx;
int l_rtype;
int l_rsecnm;
/* Read the reloc from the file. */
if (bfd_read (&ext, sizeof ext, 1, abfd) != sizeof ext)
{
bfd_set_error (bfd_error_system_call);
return false;
}
/* Swap in the fields. */
l_vaddr = bfd_h_get_32 (abfd, ext.l_vaddr);
l_symndx = bfd_h_get_32 (abfd, ext.l_symndx);
l_rtype = bfd_h_get_16 (abfd, ext.l_rtype);
l_rsecnm = bfd_h_get_16 (abfd, ext.l_rsecnm);
/* Work out the arelent fields. */
if (sym != NULL)
{
/* This is an import. sym_ptr_ptr is filled in by
nlm_canonicalize_reloc. */
rel->sym_ptr_ptr = NULL;
}
else
{
asection *sec;
if (l_symndx == 0)
sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
else if (l_symndx == 1)
sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
else if (l_symndx == 2)
sec = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
else
{
bfd_set_error (bfd_error_bad_value);
return false;
}
rel->sym_ptr_ptr = sec->symbol_ptr_ptr;
}
rel->address = l_vaddr;
rel->addend = 0;
BFD_ASSERT ((l_rtype & 0xff) < HOWTO_COUNT);
rel->howto = nlm_powerpc_howto_table + (l_rtype & 0xff);
BFD_ASSERT (rel->howto->name != NULL
&& ((l_rtype & 0x8000) != 0
? (rel->howto->complain_on_overflow
== complain_overflow_signed)
: (rel->howto->complain_on_overflow
== complain_overflow_bitfield))
&& ((l_rtype >> 8) & 0x1f) == rel->howto->bitsize - 1);
if (l_rsecnm == 0)
*secp = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
else if (l_rsecnm == 1)
*secp = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
else
{
bfd_set_error (bfd_error_bad_value);
return false;
}
return true;
}
/* Mangle PowerPC NLM relocs for output. */
static boolean
nlm_powerpc_mangle_relocs (abfd, sec, data, offset, count)
bfd *abfd;
asection *sec;
PTR data;
bfd_vma offset;
bfd_size_type count;
{
return true;
}
/* Read a PowerPC NLM import record */
static boolean
nlm_powerpc_read_import (abfd, sym)
bfd *abfd;
nlmNAME(symbol_type) *sym;
{
struct nlm_relent *nlm_relocs; /* relocation records for symbol */
bfd_size_type rcount; /* number of relocs */
bfd_byte temp[NLM_TARGET_LONG_SIZE]; /* temporary 32-bit value */
unsigned char symlength; /* length of symbol name */
if (bfd_read ((PTR) &symlength, sizeof (symlength), 1, abfd)
!= sizeof (symlength))
{
bfd_set_error (bfd_error_system_call);
return (false);
}
sym -> symbol.the_bfd = abfd;
sym -> symbol.name = bfd_alloc (abfd, symlength + 1);
if (bfd_read ((PTR) sym -> symbol.name, symlength, 1, abfd)
!= symlength)
{
bfd_set_error (bfd_error_system_call);
return (false);
}
sym -> symbol.flags = 0;
sym -> symbol.value = 0;
sym -> symbol.section = &bfd_und_section;
if (bfd_read ((PTR) temp, sizeof (temp), 1, abfd) != sizeof (temp))
{
bfd_set_error (bfd_error_system_call);
return (false);
}
rcount = bfd_h_get_32 (abfd, temp);
nlm_relocs = ((struct nlm_relent *)
bfd_alloc (abfd, rcount * sizeof (struct nlm_relent)));
if (nlm_relocs == (struct nlm_relent *) NULL)
{
bfd_set_error (bfd_error_no_memory);
return false;
}
sym -> relocs = nlm_relocs;
sym -> rcnt = 0;
while (sym -> rcnt < rcount)
{
asection *section;
if (nlm_powerpc_read_reloc (abfd, sym, &section,
&nlm_relocs -> reloc)
== false)
return false;
nlm_relocs -> section = section;
nlm_relocs++;
sym -> rcnt++;
}
return true;
}
/* Write a PowerPC NLM reloc. */
static boolean
nlm_powerpc_write_import (abfd, sec, rel)
bfd *abfd;
asection *sec;
arelent *rel;
{
struct nlm32_powerpc_external_reloc ext;
asymbol *sym;
asection *symsec;
unsigned long l_symndx;
int l_rtype;
int l_rsecnm;
const reloc_howto_type *howto;
bfd_h_put_32 (abfd, rel->address, ext.l_vaddr);
sym = *rel->sym_ptr_ptr;
symsec = bfd_get_section (sym);
if (symsec == &bfd_und_section)
l_symndx = 0;
else if (symsec == bfd_get_section_by_name (abfd, NLM_CODE_NAME))
l_symndx = 0;
else if (symsec == bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME))
l_symndx = 1;
else if (symsec == bfd_get_section_by_name (abfd,
NLM_UNINITIALIZED_DATA_NAME))
l_symndx = 2;
else
{
bfd_set_error (bfd_error_bad_value);
return false;
}
bfd_h_put_32 (abfd, (bfd_vma) l_symndx, ext.l_symndx);
for (howto = nlm_powerpc_howto_table;
howto < nlm_powerpc_howto_table + HOWTO_COUNT;
howto++)
{
if (howto->rightshift == rel->howto->rightshift
&& howto->size == rel->howto->size
&& howto->bitsize == rel->howto->bitsize
&& howto->pc_relative == rel->howto->pc_relative
&& howto->bitpos == rel->howto->bitpos
&& howto->partial_inplace == rel->howto->partial_inplace
&& howto->src_mask == rel->howto->src_mask
&& howto->dst_mask == rel->howto->dst_mask
&& howto->pcrel_offset == rel->howto->pcrel_offset)
break;
}
if (howto >= nlm_powerpc_howto_table + HOWTO_COUNT)
{
bfd_set_error (bfd_error_bad_value);
return false;
}
l_rtype = howto->type;
if (howto->complain_on_overflow == complain_overflow_signed)
l_rtype |= 0x8000;
l_rtype |= (howto->bitsize - 1) << 8;
bfd_h_put_16 (abfd, (bfd_vma) l_rtype, ext.l_rtype);
if (sec == bfd_get_section_by_name (abfd, NLM_CODE_NAME))
l_rsecnm = 0;
else if (sec == bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME))
l_rsecnm = 1;
else
{
bfd_set_error (bfd_error_bad_value);
return false;
}
bfd_h_put_16 (abfd, (bfd_vma) l_rsecnm, ext.l_rsecnm);
if (bfd_write (&ext, sizeof ext, 1, abfd) != sizeof ext)
return false;
return true;
}
/* Write a PowerPC NLM external symbol. */
static boolean
nlm_powerpc_write_external (abfd, count, sym, relocs)
bfd *abfd;
bfd_size_type count;
asymbol *sym;
struct reloc_and_sec *relocs;
{
int i;
bfd_byte len;
unsigned char temp[NLM_TARGET_LONG_SIZE];
len = strlen (sym->name);
if ((bfd_write (&len, sizeof (bfd_byte), 1, abfd) != sizeof(bfd_byte))
|| bfd_write (sym->name, len, 1, abfd) != len)
{
bfd_set_error (bfd_error_system_call);
return false;
}
bfd_put_32 (abfd, count, temp);
if (bfd_write (temp, sizeof(temp), 1, abfd) != sizeof (temp))
{
bfd_set_error (bfd_error_system_call);
return false;
}
for (i = 0; i < count; i++)
{
if (nlm_powerpc_write_import (abfd, relocs[i].sec,
relocs[i].rel) == false)
return false;
}
return true;
}
#include "nlmswap.h"
static const struct nlm_backend_data nlm32_powerpc_backend =
{
"NetWare PowerPC Module \032",
sizeof (Nlm32_powerpc_External_Fixed_Header),
sizeof (struct nlm32_powerpc_external_prefix_header),
bfd_arch_powerpc,
0,
false,
nlm_powerpc_backend_object_p,
nlm_powerpc_write_prefix,
nlm_powerpc_read_reloc,
nlm_powerpc_mangle_relocs,
nlm_powerpc_read_import,
nlm_powerpc_write_import,
0, /* set_public_section */
0, /* get_public_offset */
nlm_swap_fixed_header_in,
nlm_swap_fixed_header_out,
nlm_powerpc_write_external,
0, /* write_export */
};
#define TARGET_BIG_NAME "nlm32-powerpc"
#define TARGET_BIG_SYM nlmNAME(powerpc_vec)
#define TARGET_BACKEND_DATA &nlm32_powerpc_backend
#include "nlm-target.h"