Index: bfd/elf32-i386.c |
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c |
index d1873051b4d9bc692b86b23b6277e3718f00864f..7d3652d81ce983ae3499e279427c61feb6db557a 100644 |
--- a/bfd/elf32-i386.c |
+++ b/bfd/elf32-i386.c |
@@ -1,6 +1,6 @@ |
/* Intel 80386/80486-specific support for 32-bit ELF |
Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, |
- 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 |
+ 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 |
Free Software Foundation, Inc. |
This file is part of BFD, the Binary File Descriptor library. |
@@ -25,6 +25,7 @@ |
#include "bfdlink.h" |
#include "libbfd.h" |
#include "elf-bfd.h" |
+#include "elf-nacl.h" |
#include "elf-vxworks.h" |
#include "bfd_stdint.h" |
#include "objalloc.h" |
@@ -1000,9 +1001,9 @@ elf_i386_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info) |
if (htab == NULL) |
return FALSE; |
- htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss"); |
+ htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss"); |
if (!info->shared) |
- htab->srelbss = bfd_get_section_by_name (dynobj, ".rel.bss"); |
+ htab->srelbss = bfd_get_linker_section (dynobj, ".rel.bss"); |
if (!htab->sdynbss |
|| (!info->shared && !htab->srelbss)) |
@@ -1014,22 +1015,17 @@ elf_i386_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info) |
return FALSE; |
if (!info->no_ld_generated_unwind_info |
- && bfd_get_section_by_name (dynobj, ".eh_frame") == NULL |
+ && htab->plt_eh_frame == NULL |
&& htab->elf.splt != NULL) |
{ |
- flagword flags = get_elf_backend_data (dynobj)->dynamic_sec_flags; |
+ flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY |
+ | SEC_HAS_CONTENTS | SEC_IN_MEMORY |
+ | SEC_LINKER_CREATED); |
htab->plt_eh_frame |
- = bfd_make_section_with_flags (dynobj, ".eh_frame", |
- flags | SEC_READONLY); |
+ = bfd_make_section_anyway_with_flags (dynobj, ".eh_frame", flags); |
if (htab->plt_eh_frame == NULL |
|| !bfd_set_section_alignment (dynobj, htab->plt_eh_frame, 2)) |
return FALSE; |
- |
- htab->plt_eh_frame->size = sizeof (elf_i386_eh_frame_plt); |
- htab->plt_eh_frame->contents |
- = bfd_alloc (dynobj, htab->plt_eh_frame->size); |
- memcpy (htab->plt_eh_frame->contents, elf_i386_eh_frame_plt, |
- sizeof (elf_i386_eh_frame_plt)); |
} |
return TRUE; |
@@ -2177,13 +2173,6 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info, |
} |
} |
- if (h->size == 0) |
- { |
- (*_bfd_error_handler) (_("dynamic variable `%s' is zero size"), |
- h->root.root.string); |
- return TRUE; |
- } |
- |
/* We must allocate the symbol in our .dynbss section, which will |
become part of the .bss section of the executable. There will be |
an entry for this symbol in the .dynsym section. The dynamic |
@@ -2197,7 +2186,7 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info, |
/* We must generate a R_386_COPY reloc to tell the dynamic linker to |
copy the initial value out of the dynamic object and into the |
runtime process image. */ |
- if ((h->root.u.def.section->flags & SEC_ALLOC) != 0) |
+ if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0) |
{ |
htab->srelbss->size += sizeof (Elf32_External_Rel); |
h->needs_copy = 1; |
@@ -2570,7 +2559,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) |
/* Set the contents of the .interp section to the interpreter. */ |
if (info->executable) |
{ |
- s = bfd_get_section_by_name (dynobj, ".interp"); |
+ s = bfd_get_linker_section (dynobj, ".interp"); |
if (s == NULL) |
abort (); |
s->size = sizeof ELF_DYNAMIC_INTERPRETER; |
@@ -2709,7 +2698,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) |
it's not incremented, so in order to compute the space reserved |
for them, it suffices to multiply the reloc count by the jump |
slot size. |
- |
+ |
PR ld/13302: We start next_irelative_index at the end of .rela.plt |
so that R_386_IRELATIVE entries come last. */ |
if (htab->elf.srelplt) |
@@ -2730,7 +2719,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) |
FALSE, FALSE, FALSE); |
/* Don't allocate .got.plt section if there are no GOT nor PLT |
- entries and there is no refeence to _GLOBAL_OFFSET_TABLE_. */ |
+ entries and there is no reference to _GLOBAL_OFFSET_TABLE_. */ |
if ((got == NULL |
|| !got->ref_regular_nonweak) |
&& (htab->elf.sgotplt->size |
@@ -2746,6 +2735,14 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) |
htab->elf.sgotplt->size = 0; |
} |
+ |
+ if (htab->plt_eh_frame != NULL |
+ && htab->elf.splt != NULL |
+ && htab->elf.splt->size != 0 |
+ && !bfd_is_abs_section (htab->elf.splt->output_section) |
+ && _bfd_elf_eh_frame_present (info)) |
+ htab->plt_eh_frame->size = sizeof (elf_i386_eh_frame_plt); |
+ |
/* We now have determined the sizes of the various dynamic sections. |
Allocate memory for them. */ |
relocs = FALSE; |
@@ -2757,11 +2754,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) |
continue; |
if (s == htab->elf.splt |
- || s == htab->elf.sgot |
- || s == htab->elf.sgotplt |
- || s == htab->elf.iplt |
- || s == htab->elf.igotplt |
- || s == htab->sdynbss) |
+ || s == htab->elf.sgot) |
{ |
/* Strip this section if we don't need it; see the |
comment below. */ |
@@ -2772,6 +2765,14 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) |
if (htab->elf.hplt != NULL) |
strip_section = FALSE; |
} |
+ else if (s == htab->elf.sgotplt |
+ || s == htab->elf.iplt |
+ || s == htab->elf.igotplt |
+ || s == htab->plt_eh_frame |
+ || s == htab->sdynbss) |
+ { |
+ /* Strip these too. */ |
+ } |
else if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rel")) |
{ |
if (s->size != 0 |
@@ -2819,11 +2820,13 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) |
} |
if (htab->plt_eh_frame != NULL |
- && htab->elf.splt != NULL |
- && htab->elf.splt->size != 0 |
- && (htab->elf.splt->flags & SEC_EXCLUDE) == 0) |
- bfd_put_32 (dynobj, htab->elf.splt->size, |
- htab->plt_eh_frame->contents + PLT_FDE_LEN_OFFSET); |
+ && htab->plt_eh_frame->contents != NULL) |
+ { |
+ memcpy (htab->plt_eh_frame->contents, elf_i386_eh_frame_plt, |
+ sizeof (elf_i386_eh_frame_plt)); |
+ bfd_put_32 (dynobj, htab->elf.splt->size, |
+ htab->plt_eh_frame->contents + PLT_FDE_LEN_OFFSET); |
+ } |
if (htab->elf.dynamic_sections_created) |
{ |
@@ -3196,9 +3199,9 @@ elf_i386_relocate_section (bfd *output_bfd, |
unresolved_reloc, warned); |
} |
- if (sec != NULL && elf_discarded_section (sec)) |
+ if (sec != NULL && discarded_section (sec)) |
RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, |
- rel, relend, howto, contents); |
+ rel, 1, relend, howto, 0, contents); |
if (info->relocatable) |
continue; |
@@ -3257,7 +3260,6 @@ elf_i386_relocate_section (bfd *output_bfd, |
bfd_byte *loc; |
asection *sreloc; |
bfd_vma offset; |
- bfd_boolean relocate; |
/* Need a dynamic relocation to get the real function |
adddress. */ |
@@ -3278,14 +3280,15 @@ elf_i386_relocate_section (bfd *output_bfd, |
|| info->executable) |
{ |
/* This symbol is resolved locally. */ |
- outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE); |
- relocate = TRUE; |
+ outrel.r_info = ELF32_R_INFO (0, R_386_IRELATIVE); |
+ bfd_put_32 (output_bfd, |
+ (h->root.u.def.value |
+ + h->root.u.def.section->output_section->vma |
+ + h->root.u.def.section->output_offset), |
+ contents + offset); |
} |
else |
- { |
- outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); |
- relocate = FALSE; |
- } |
+ outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); |
sreloc = htab->elf.irelifunc; |
loc = sreloc->contents; |
@@ -3298,8 +3301,7 @@ elf_i386_relocate_section (bfd *output_bfd, |
we need to include the symbol value so that it |
becomes an addend for the dynamic reloc. For an |
internal symbol, we have updated addend. */ |
- if (! relocate) |
- continue; |
+ continue; |
} |
/* FALLTHROUGH */ |
case R_386_PC32: |
@@ -3511,6 +3513,7 @@ elf_i386_relocate_section (bfd *output_bfd, |
return FALSE; |
} |
else if (!info->executable |
+ && !SYMBOLIC_BIND (info, h) |
&& h->type == STT_FUNC |
&& ELF_ST_VISIBILITY (h->other) == STV_PROTECTED) |
{ |
@@ -4606,17 +4609,6 @@ do_glob_dat: |
bfd_elf32_swap_reloc_out (output_bfd, &rel, loc); |
} |
- /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. SYM may |
- be NULL for local symbols. |
- |
- On VxWorks, the _GLOBAL_OFFSET_TABLE_ symbol is not absolute: it |
- is relative to the ".got" section. */ |
- if (sym != NULL |
- && (strcmp (h->root.root.string, "_DYNAMIC") == 0 |
- || (!abed->is_vxworks |
- && h == htab->elf.hgot))) |
- sym->st_shndx = SHN_ABS; |
- |
return TRUE; |
} |
@@ -4670,7 +4662,7 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd, |
return FALSE; |
dynobj = htab->elf.dynobj; |
- sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); |
+ sdyn = bfd_get_linker_section (dynobj, ".dynamic"); |
abed = get_elf_i386_backend_data (output_bfd); |
if (htab->elf.dynamic_sections_created) |
@@ -4855,7 +4847,8 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd, |
} |
/* Adjust .eh_frame for .plt section. */ |
- if (htab->plt_eh_frame != NULL) |
+ if (htab->plt_eh_frame != NULL |
+ && htab->plt_eh_frame->contents != NULL) |
{ |
if (htab->elf.splt != NULL |
&& htab->elf.splt->size != 0 |
@@ -4872,7 +4865,7 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd, |
+ PLT_FDE_START_OFFSET); |
} |
if (htab->plt_eh_frame->sec_info_type |
- == ELF_INFO_TYPE_EH_FRAME) |
+ == SEC_INFO_TYPE_EH_FRAME) |
{ |
if (! _bfd_elf_write_section_eh_frame (output_bfd, info, |
htab->plt_eh_frame, |
@@ -5117,7 +5110,10 @@ elf_i386_nacl_pic_plt0_entry[sizeof (elf_i386_nacl_plt0_entry)] = |
0x8b, 0x4b, 0x08, /* mov 0x8(%ebx), %ecx */ |
0x83, 0xe1, 0xe0, /* and $NACLMASK, %ecx */ |
0xff, 0xe1, /* jmp *%ecx */ |
- 0x90 /* nop */ |
+ |
+ /* This is expected to be the same size as elf_i386_nacl_plt0_entry, |
+ so pad to that size with nop instructions. */ |
+ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 |
}; |
static const bfd_byte elf_i386_nacl_pic_plt_entry[NACL_PLT_ENTRY_SIZE] = |
@@ -5211,8 +5207,17 @@ static const struct elf_i386_backend_data elf_i386_nacl_arch_bed = |
#undef elf_backend_arch_data |
#define elf_backend_arch_data &elf_i386_nacl_arch_bed |
+#undef elf_backend_modify_segment_map |
+#define elf_backend_modify_segment_map nacl_modify_segment_map |
+#undef elf_backend_modify_program_headers |
+#define elf_backend_modify_program_headers nacl_modify_program_headers |
+ |
#include "elf32-target.h" |
+/* Restore defaults. */ |
+#undef elf_backend_modify_segment_map |
+#undef elf_backend_modify_program_headers |
+ |
/* VxWorks support. */ |
#undef TARGET_LITTLE_SYM |