diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2011-05-07 14:12:59 +0000 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2011-05-07 14:12:59 +0000 |
commit | 310fd250b9bdab1eae5303f363577e30b2932a77 (patch) | |
tree | 728a50e468368a77342a5f692954d19fc0c938d6 /bfd | |
parent | 70778fc76803fd416f0bb898773811f12baa0714 (diff) | |
download | gdb-310fd250b9bdab1eae5303f363577e30b2932a77.zip gdb-310fd250b9bdab1eae5303f363577e30b2932a77.tar.gz gdb-310fd250b9bdab1eae5303f363577e30b2932a77.tar.bz2 |
Reverse copy .ctors/.dtors sections if needed.
bfd/
2011-05-07 H.J. Lu <hongjiu.lu@intel.com>
PR ld/12730
* elf.c (_bfd_elf_section_offset): Check SEC_ELF_REVERSE_COPY.
* elflink.c (elf_link_input_bfd): Reverse copy .ctors/.dtors
sections if needed.
* section.c (SEC_ELF_REVERSE_COPY): New.
* bfd-in2.h: Regenerated.
ld/testsuite/
2011-05-07 H.J. Lu <hongjiu.lu@intel.com>
PR ld/12730
* ld-elf/elf.exp (array_tests): Add "pr12730".
(array_tests_pie): New.
(array_tests_static): Add -static for "static init array mixed".
Add "static pr12730". Run array_tests_pie for Linux.
* ld-elf/init-mixed.c (ctor1007): Renamed to ...
(ctor1007a): This.
(ctor1007b): New.
(ctors1007): Remove ctor1007. Add ctor1007b and ctor1007a.
(dtor1007): Renamed to ...
(dtor1007a): This.
(dtor1007b): New.
(dtors1007): Remove dtor1007. Add dtor1007b and dtor1007a.
(ctor65535): Renamed to ...
(ctor65535a): This.
(ctor65535b): New.
(ctors65535): Remove ctor65535. Add ctor65535b and ctor65535a.
(dtor65535): Renamed to ...
(dtor65535a): This.
(dtor65535b): New.
(dtors65535): Remove dtor65535. Add dtor65535b and dtor65535a.
* ld-elf/pr12730.cc: New.
* ld-elf/pr12730.out: Likewise.
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 11 | ||||
-rw-r--r-- | bfd/bfd-in2.h | 5 | ||||
-rw-r--r-- | bfd/elf.c | 6 | ||||
-rw-r--r-- | bfd/elflink.c | 80 | ||||
-rw-r--r-- | bfd/section.c | 5 |
5 files changed, 91 insertions, 16 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 73b15f2..eb055ea 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,14 @@ +2011-05-07 H.J. Lu <hongjiu.lu@intel.com> + + PR ld/12730 + * elf.c (_bfd_elf_section_offset): Check SEC_ELF_REVERSE_COPY. + + * elflink.c (elf_link_input_bfd): Reverse copy .ctors/.dtors + sections if needed. + + * section.c (SEC_ELF_REVERSE_COPY): New. + * bfd-in2.h: Regenerated. + 2011-05-07 Anders Kaseorg <andersk@ksplice.com> PR 12739 diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index aa12c8a..5076ccf 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -1320,6 +1320,11 @@ typedef struct bfd_section sections. */ #define SEC_COFF_SHARED_LIBRARY 0x4000000 + /* This input section should be copied to output in reverse order + as an array of pointers. This is for ELF linker internal use + only. */ +#define SEC_ELF_REVERSE_COPY 0x4000000 + /* This section contains data which may be shared with other executables or shared objects. This is for COFF only. */ #define SEC_COFF_SHARED 0x8000000 @@ -9379,6 +9379,12 @@ _bfd_elf_section_offset (bfd *abfd, case ELF_INFO_TYPE_EH_FRAME: return _bfd_elf_eh_frame_section_offset (abfd, info, sec, offset); default: + if ((sec->flags & SEC_ELF_REVERSE_COPY) != 0) + { + const struct elf_backend_data *bed = get_elf_backend_data (abfd); + bfd_size_type address_size = bed->s->arch_size / 8; + offset = sec->size - offset - address_size; + } return offset; } } diff --git a/bfd/elflink.c b/bfd/elflink.c index 082355d..e4f728d 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -9120,6 +9120,9 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) asection *o; const struct elf_backend_data *bed; struct elf_link_hash_entry **sym_hashes; + bfd_size_type address_size; + bfd_vma r_type_mask; + int r_sym_shift; output_bfd = finfo->output_bfd; bed = get_elf_backend_data (output_bfd); @@ -9290,6 +9293,19 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) *pindex = indx; } + if (bed->s->arch_size == 32) + { + r_type_mask = 0xff; + r_sym_shift = 8; + address_size = 4; + } + else + { + r_type_mask = 0xffffffff; + r_sym_shift = 32; + address_size = 8; + } + /* Relocate the contents of each section. */ sym_hashes = elf_sym_hashes (input_bfd); for (o = input_bfd->sections; o != NULL; o = o->next) @@ -9394,8 +9410,6 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) { Elf_Internal_Rela *internal_relocs; Elf_Internal_Rela *rel, *relend; - bfd_vma r_type_mask; - int r_sym_shift; int action_discarded; int ret; @@ -9407,15 +9421,27 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) && o->reloc_count > 0) return FALSE; - if (bed->s->arch_size == 32) + /* We need to reverse-copy input .ctors/.dtors sections if + they are placed in .init_array/.finit_array for output. */ + if (o->size > address_size + && ((strncmp (o->name, ".ctors", 6) == 0 + && strcmp (o->output_section->name, + ".init_array") == 0) + || (strncmp (o->name, ".dtors", 6) == 0 + && strcmp (o->output_section->name, + ".fini_array") == 0)) + && (o->name[6] == 0 || o->name[6] == '.')) { - r_type_mask = 0xff; - r_sym_shift = 8; - } - else - { - r_type_mask = 0xffffffff; - r_sym_shift = 32; + if (o->size != o->reloc_count * address_size) + { + (*_bfd_error_handler) + (_("error: %B: size of section %A is not " + "multiple of address size"), + input_bfd, o); + bfd_set_error (bfd_error_on_input); + return FALSE; + } + o->flags |= SEC_ELF_REVERSE_COPY; } action_discarded = -1; @@ -9876,12 +9902,34 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) default: { /* FIXME: octets_per_byte. */ - if (! (o->flags & SEC_EXCLUDE) - && ! bfd_set_section_contents (output_bfd, o->output_section, - contents, - (file_ptr) o->output_offset, - o->size)) - return FALSE; + if (! (o->flags & SEC_EXCLUDE)) + { + file_ptr offset = (file_ptr) o->output_offset; + bfd_size_type todo = o->size; + if ((o->flags & SEC_ELF_REVERSE_COPY)) + { + /* Reverse-copy input section to output. */ + do + { + todo -= address_size; + if (! bfd_set_section_contents (output_bfd, + o->output_section, + contents + todo, + offset, + address_size)) + return FALSE; + if (todo == 0) + break; + offset += address_size; + } + while (1); + } + else if (! bfd_set_section_contents (output_bfd, + o->output_section, + contents, + offset, todo)) + return FALSE; + } } break; } diff --git a/bfd/section.c b/bfd/section.c index 65ac5e6..3cd7e65 100644 --- a/bfd/section.c +++ b/bfd/section.c @@ -327,6 +327,11 @@ CODE_FRAGMENT . sections. *} .#define SEC_COFF_SHARED_LIBRARY 0x4000000 . +. {* This input section should be copied to output in reverse order +. as an array of pointers. This is for ELF linker internal use +. only. *} +.#define SEC_ELF_REVERSE_COPY 0x4000000 +. . {* This section contains data which may be shared with other . executables or shared objects. This is for COFF only. *} .#define SEC_COFF_SHARED 0x8000000 |