/* X86-64 specific support for 64-bit ELF
- Copyright 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright 2000, 2001, 2002, 2003, 2004, 2005
+ Free Software Foundation, Inc.
Contributed by Jan Hubicka <jh@suse.cz>.
This file is part of BFD, the Binary File Descriptor library.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
#include "bfd.h"
#include "sysdep.h"
if (!htab->sgot || !htab->sgotplt)
abort ();
- htab->srelgot = bfd_make_section (dynobj, ".rela.got");
+ htab->srelgot = bfd_make_section_with_flags (dynobj, ".rela.got",
+ (SEC_ALLOC | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY
+ | SEC_LINKER_CREATED
+ | SEC_READONLY));
if (htab->srelgot == NULL
- || ! bfd_set_section_flags (dynobj, htab->srelgot,
- (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
- | SEC_IN_MEMORY | SEC_LINKER_CREATED
- | SEC_READONLY))
|| ! bfd_set_section_alignment (dynobj, htab->srelgot, 3))
return FALSE;
return TRUE;
{
flagword flags;
- sreloc = bfd_make_section (dynobj, name);
flags = (SEC_HAS_CONTENTS | SEC_READONLY
| SEC_IN_MEMORY | SEC_LINKER_CREATED);
if ((sec->flags & SEC_ALLOC) != 0)
flags |= SEC_ALLOC | SEC_LOAD;
+ sreloc = bfd_make_section_with_flags (dynobj,
+ name,
+ flags);
if (sreloc == NULL
- || ! bfd_set_section_flags (dynobj, sreloc, flags)
|| ! bfd_set_section_alignment (dynobj, sreloc, 3))
return FALSE;
}
struct elf64_x86_64_dyn_relocs *p;
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+ while (h->root.type == bfd_link_hash_indirect
+ || h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
eh = (struct elf64_x86_64_link_hash_entry *) h;
for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next)
function which decides whether anything needs to go
into these sections. */
- _bfd_strip_section_from_output (info, s);
+ s->flags |= SEC_EXCLUDE;
continue;
}
return address - htab->tls_size - htab->tls_sec->vma;
}
+/* Is the instruction before OFFSET in CONTENTS a 32bit relative
+ branch? */
+
+static bfd_boolean
+is_32bit_relative_branch (bfd_byte *contents, bfd_vma offset)
+{
+ /* Opcode Instruction
+ 0xe8 call
+ 0xe9 jump
+ 0x0f 0x8x conditional jump */
+ return ((offset > 0
+ && (contents [offset - 1] == 0xe8
+ || contents [offset - 1] == 0xe9))
+ || (offset > 1
+ && contents [offset - 2] == 0x0f
+ && (contents [offset - 1] & 0xf0) == 0x80));
+}
+
/* Relocate an x86_64 ELF section. */
static bfd_boolean
if (info->shared
&& !SYMBOL_REFERENCES_LOCAL (info, h)
&& (input_section->flags & SEC_ALLOC) != 0
- && (input_section->flags & SEC_READONLY) != 0)
+ && (input_section->flags & SEC_READONLY) != 0
+ && (!h->def_regular
+ || r_type != R_X86_64_PC32
+ || h->type != STT_FUNC
+ || ELF_ST_VISIBILITY (h->other) != STV_PROTECTED
+ || !is_32bit_relative_branch (contents,
+ rel->r_offset)))
{
- (*_bfd_error_handler)
- (_("%B: relocation %s against `%s' can not be used when making a shared object; recompile with -fPIC"),
- input_bfd,
- x86_64_elf_howto_table[r_type].name,
- (h) ? h->root.root.string : "a local symbol");
+ if (h->def_regular
+ && r_type == R_X86_64_PC32
+ && h->type == STT_FUNC
+ && ELF_ST_VISIBILITY (h->other) == STV_PROTECTED)
+ (*_bfd_error_handler)
+ (_("%B: relocation R_X86_64_PC32 against protected function `%s' can not be used when making a shared object"),
+ input_bfd, h->root.root.string);
+ else
+ (*_bfd_error_handler)
+ (_("%B: relocation %s against `%s' can not be used when making a shared object; recompile with -fPIC"),
+ input_bfd, x86_64_elf_howto_table[r_type].name,
+ h->root.root.string);
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
is called when elfcode.h finds a section with an unknown type. */
static bfd_boolean
-elf64_x86_64_section_from_shdr (bfd *abfd, Elf_Internal_Shdr *hdr, const char *name)
+elf64_x86_64_section_from_shdr (bfd *abfd,
+ Elf_Internal_Shdr *hdr,
+ const char *name,
+ int shindex)
{
if (hdr->sh_type != SHT_X86_64_UNWIND)
return FALSE;
- if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
+ if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
return FALSE;
return TRUE;