/* PowerPC-specific support for 32-bit ELF
Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
- 2004, 2005, 2006 Free Software Foundation, Inc.
+ 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support.
This file is part of BFD, the Binary File Descriptor library.
suggestions from the in-progress Embedded PowerPC ABI, and that
information may also not match. */
+#include <stdarg.h>
#include "bfd.h"
#include "sysdep.h"
#include "bfdlink.h"
return ppc_elf_howto_table[r];
};
+static reloc_howto_type *
+ppc_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+ const char *r_name)
+{
+ unsigned int i;
+
+ for (i = 0;
+ i < sizeof (ppc_elf_howto_raw) / sizeof (ppc_elf_howto_raw[0]);
+ i++)
+ if (ppc_elf_howto_raw[i].name != NULL
+ && strcasecmp (ppc_elf_howto_raw[i].name, r_name) == 0)
+ return &ppc_elf_howto_raw[i];
+
+ return NULL;
+}
+
/* Set the howto pointer for a PowerPC ELF reloc. */
static void
return TRUE;
}
+static char *
+ppc_elf_write_core_note (bfd *abfd, char *buf, int *bufsiz, int note_type, ...)
+{
+ switch (note_type)
+ {
+ default:
+ return NULL;
+
+ case NT_PRPSINFO:
+ {
+ char data[128];
+ va_list ap;
+
+ va_start (ap, note_type);
+ memset (data, 0, 32);
+ strncpy (data + 32, va_arg (ap, const char *), 16);
+ strncpy (data + 48, va_arg (ap, const char *), 80);
+ va_end (ap);
+ return elfcore_write_note (abfd, buf, bufsiz,
+ "CORE", note_type, data, sizeof (data));
+ }
+
+ case NT_PRSTATUS:
+ {
+ char data[268];
+ va_list ap;
+ long pid;
+ int cursig;
+ const void *greg;
+
+ va_start (ap, note_type);
+ memset (data, 0, 72);
+ pid = va_arg (ap, long);
+ bfd_put_32 (abfd, pid, data + 24);
+ cursig = va_arg (ap, int);
+ bfd_put_16 (abfd, cursig, data + 12);
+ greg = va_arg (ap, const void *);
+ memcpy (data + 72, greg, 192);
+ memset (data + 264, 0, 4);
+ va_end (ap);
+ return elfcore_write_note (abfd, buf, bufsiz,
+ "CORE", note_type, data, sizeof (data));
+ }
+ }
+}
+
/* Return address for Ith PLT stub in section PLT, for relocation REL
or (bfd_vma) -1 if it should not be included. */
static bfd_boolean
ppc_elf_write_section (bfd *abfd ATTRIBUTE_UNUSED,
+ struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
asection *asec,
bfd_byte *contents ATTRIBUTE_UNUSED)
{
static asection *
ppc_elf_gc_mark_hook (asection *sec,
- struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info,
Elf_Internal_Rela *rel,
struct elf_link_hash_entry *h,
Elf_Internal_Sym *sym)
{
if (h != NULL)
- {
- switch (ELF32_R_TYPE (rel->r_info))
- {
- case R_PPC_GNU_VTINHERIT:
- case R_PPC_GNU_VTENTRY:
- break;
-
- default:
- switch (h->root.type)
- {
- case bfd_link_hash_defined:
- case bfd_link_hash_defweak:
- return h->root.u.def.section;
-
- case bfd_link_hash_common:
- return h->root.u.c.p->section;
-
- default:
- break;
- }
- }
- }
- else
- return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
+ switch (ELF32_R_TYPE (rel->r_info))
+ {
+ case R_PPC_GNU_VTINHERIT:
+ case R_PPC_GNU_VTENTRY:
+ return NULL;
+ }
- return NULL;
+ return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
}
/* Update the got, plt and dynamic reloc reference counts for the
}
else
ent->plt.offset = (bfd_vma) -1;
-
- if (!doneone)
- {
- h->plt.plist = NULL;
- h->needs_plt = 0;
- }
}
+ else
+ ent->plt.offset = (bfd_vma) -1;
+
+ if (!doneone)
+ {
+ h->plt.plist = NULL;
+ h->needs_plt = 0;
+ }
}
else
{
asection *got2, *sreloc = NULL;
bfd_vma *local_got_offsets;
bfd_boolean ret = TRUE;
+ bfd_vma d_offset = (bfd_big_endian (output_bfd) ? 2 : 0);
#ifdef DEBUG
_bfd_error_handler ("ppc_elf_relocate_section called for %B section %A, "
got2 = bfd_get_section_by_name (input_bfd, ".got2");
- if (info->relocatable)
- {
- if (got2 == NULL)
- return TRUE;
-
- rel = relocs;
- relend = relocs + input_section->reloc_count;
- for (; rel < relend; rel++)
- {
- enum elf_ppc_reloc_type r_type;
-
- r_type = ELF32_R_TYPE (rel->r_info);
- if (r_type == R_PPC_PLTREL24
- && rel->r_addend >= 32768)
- {
- /* R_PPC_PLTREL24 is rather special. If non-zero, the
- addend specifies the GOT pointer offset within .got2. */
- rel->r_addend += got2->output_offset;
- }
- }
- return TRUE;
- }
-
/* Initialize howto table if not already done. */
if (!ppc_elf_howto_table[R_PPC_ADDR32])
ppc_elf_howto_init ();
sym_name = h->root.root.string;
}
+ if (sec != NULL && elf_discarded_section (sec))
+ {
+ /* For relocs against symbols from removed linkonce sections,
+ or sections discarded by a linker script, we just want the
+ section contents zeroed. Avoid any special processing. */
+ howto = NULL;
+ if (r_type < R_PPC_max)
+ howto = ppc_elf_howto_table[r_type];
+ _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
+ rel->r_info = 0;
+ rel->r_addend = 0;
+ continue;
+ }
+
+ if (info->relocatable)
+ {
+ if (got2 != NULL
+ && r_type == R_PPC_PLTREL24
+ && rel->r_addend >= 32768)
+ {
+ /* R_PPC_PLTREL24 is rather special. If non-zero, the
+ addend specifies the GOT pointer offset within .got2. */
+ rel->r_addend += got2->output_offset;
+ }
+ continue;
+ }
+
/* TLS optimizations. Replace instruction sequences and relocs
based on information we collected in tls_optimize. We edit
RELOCS so that --emit-relocs will output something sensible
&& (tls_mask & TLS_TPREL) == 0)
{
bfd_vma insn;
- insn = bfd_get_32 (output_bfd, contents + rel->r_offset - 2);
+ insn = bfd_get_32 (output_bfd, contents + rel->r_offset - d_offset);
insn &= 31 << 21;
insn |= 0x3c020000; /* addis 0,2,0 */
- bfd_put_32 (output_bfd, insn, contents + rel->r_offset - 2);
+ bfd_put_32 (output_bfd, insn, contents + rel->r_offset - d_offset);
r_type = R_PPC_TPREL16_HA;
rel->r_info = ELF32_R_INFO (r_symndx, r_type);
}
bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
r_type = R_PPC_TPREL16_LO;
rel->r_info = ELF32_R_INFO (r_symndx, r_type);
+
/* Was PPC_TLS which sits on insn boundary, now
- PPC_TPREL16_LO which is at insn+2. */
- rel->r_offset += 2;
+ PPC_TPREL16_LO which is at low-order half-word. */
+ rel->r_offset += d_offset;
}
break;
else
{
bfd_put_32 (output_bfd, NOP, contents + rel->r_offset);
- rel->r_offset -= 2;
+ rel->r_offset -= d_offset;
r_type = R_PPC_NONE;
}
rel->r_info = ELF32_R_INFO (r_symndx, r_type);
/* OK, it checks out. Replace the call. */
offset = rel[1].r_offset;
insn1 = bfd_get_32 (output_bfd,
- contents + rel->r_offset - 2);
+ contents + rel->r_offset - d_offset);
if ((tls_mask & tls_gd) != 0)
{
/* IE */
rel->r_info = ELF32_R_INFO (r_symndx, r_type);
rel[1].r_info = ELF32_R_INFO (r_symndx,
R_PPC_TPREL16_LO);
- rel[1].r_offset += 2;
+ rel[1].r_offset += d_offset;
rel[1].r_addend = rel->r_addend;
}
- bfd_put_32 (output_bfd, insn1, contents + rel->r_offset - 2);
+ bfd_put_32 (output_bfd, insn1, contents + rel->r_offset - d_offset);
bfd_put_32 (output_bfd, insn2, contents + offset);
if (tls_gd == 0)
{
case R_PPC_ADDR14_BRNTAKEN:
case R_PPC_UADDR32:
case R_PPC_UADDR16:
- /* r_symndx will be zero only for relocs against symbols
- from removed linkonce sections, or sections discarded by
- a linker script. */
dodyn:
- if (r_symndx == 0)
- break;
- /* Fall thru. */
-
if ((input_section->flags & SEC_ALLOC) == 0)
break;
/* Fall thru. */
but ld.so expects buggy relocs. */
osec = sec->output_section;
indx = elf_section_data (osec)->dynindx;
- BFD_ASSERT (indx > 0);
+ if (indx == 0)
+ {
+ osec = htab->elf.text_index_section;
+ indx = elf_section_data (osec)->dynindx;
+ }
+ BFD_ASSERT (indx != 0);
#ifdef DEBUG
- if (indx <= 0)
+ if (indx == 0)
printf ("indx=%ld section=%s flags=%08x name=%s\n",
indx, osec->name, osec->flags,
h->root.root.string);
#define bfd_elf32_bfd_merge_private_bfd_data ppc_elf_merge_private_bfd_data
#define bfd_elf32_bfd_relax_section ppc_elf_relax_section
#define bfd_elf32_bfd_reloc_type_lookup ppc_elf_reloc_type_lookup
+#define bfd_elf32_bfd_reloc_name_lookup ppc_elf_reloc_name_lookup
#define bfd_elf32_bfd_set_private_flags ppc_elf_set_private_flags
#define bfd_elf32_bfd_link_hash_table_create ppc_elf_link_hash_table_create
#define elf_backend_additional_program_headers ppc_elf_additional_program_headers
#define elf_backend_grok_prstatus ppc_elf_grok_prstatus
#define elf_backend_grok_psinfo ppc_elf_grok_psinfo
+#define elf_backend_write_core_note ppc_elf_write_core_note
#define elf_backend_reloc_type_class ppc_elf_reloc_type_class
#define elf_backend_begin_write_processing ppc_elf_begin_write_processing
#define elf_backend_final_write_processing ppc_elf_final_write_processing
#define elf_backend_get_sec_type_attr ppc_elf_get_sec_type_attr
#define elf_backend_plt_sym_val ppc_elf_plt_sym_val
#define elf_backend_action_discarded ppc_elf_action_discarded
+#define elf_backend_init_index_section _bfd_elf_init_1_index_section
#include "elf32-target.h"