diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2014-12-18 11:09:28 -0800 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2015-01-06 15:38:25 -0800 |
commit | 4fc1b9d43cbce7571264a0011c87258b78252750 (patch) | |
tree | 93ec540f596de570077e84135d9e1a78ac4b67a4 /gold/x86_64.cc | |
parent | e7287c7f647870093b8ab5ffea0732ffdb8c4d66 (diff) | |
download | fsf-binutils-gdb-4fc1b9d43cbce7571264a0011c87258b78252750.zip fsf-binutils-gdb-4fc1b9d43cbce7571264a0011c87258b78252750.tar.gz fsf-binutils-gdb-4fc1b9d43cbce7571264a0011c87258b78252750.tar.bz2 |
Handle stack split for x32
X32 uses cmp %fs:NN,%esp, lea NN(%rsp),%r10d, lea NN(%rsp),%r11d,
instead of cmp %fs:NN,%rsp, lea NN(%rsp),%r10, lea NN(%rsp),%r11.
This patch handles it.
PR gold/17729
* configure.ac (DEFAULT_TARGET_X86_64): Don't set for x32.
(DEFAULT_TARGET_X32): Set for x32.
* x86_64.cc (cmp_insn_32): New.
(lea_r10_insn_32): Likewise.
(lea_r11_insn_32): Likewise.
(cmp_insn_64): Likewise.
(lea_r10_insn_64): Likewise.
(lea_r11_insn_64): Likewise.
(Target_x86_64<size>::do_calls_non_split): Handle x32.
* testsuite/Makefile.am (check_SCRIPTS): Add split_x32.sh.
(check_DATA): Add split_x32 files.
(split_x32_[1234n].o): New targets.
(split_x32_[124]): New targets.
(split_x32_[1234r].stdout): New targets.
* testsuite/split_x32.sh: New file.
* testsuite/split_x32_1.s: Likewise.
* testsuite/split_x32_2.s: Likewise.
* testsuite/split_x32_3.s: Likewise.
* testsuite/split_x32_4.s: Likewise.
* testsuite/split_x32_n.s: Likewise.
* configure: Regenerated.
* testsuite/Makefile.in: Likewise.
Diffstat (limited to 'gold/x86_64.cc')
-rw-r--r-- | gold/x86_64.cc | 33 |
1 files changed, 28 insertions, 5 deletions
diff --git a/gold/x86_64.cc b/gold/x86_64.cc index c368b03..dd6c07b 100644 --- a/gold/x86_64.cc +++ b/gold/x86_64.cc @@ -4463,6 +4463,14 @@ Target_x86_64<size>::do_ehframe_datarel_base() const // code. We have to change the function so that it always ensures // that it has enough stack space to run some random function. +static const unsigned char cmp_insn_32[] = { 0x64, 0x3b, 0x24, 0x25 }; +static const unsigned char lea_r10_insn_32[] = { 0x44, 0x8d, 0x94, 0x24 }; +static const unsigned char lea_r11_insn_32[] = { 0x44, 0x8d, 0x9c, 0x24 }; + +static const unsigned char cmp_insn_64[] = { 0x64, 0x48, 0x3b, 0x24, 0x25 }; +static const unsigned char lea_r10_insn_64[] = { 0x4c, 0x8d, 0x94, 0x24 }; +static const unsigned char lea_r11_insn_64[] = { 0x4c, 0x8d, 0x9c, 0x24 }; + template<int size> void Target_x86_64<size>::do_calls_non_split(Relobj* object, unsigned int shndx, @@ -4473,25 +4481,40 @@ Target_x86_64<size>::do_calls_non_split(Relobj* object, unsigned int shndx, std::string* from, std::string* to) const { + const char* const cmp_insn = reinterpret_cast<const char*> + (size == 32 ? cmp_insn_32 : cmp_insn_64); + const char* const lea_r10_insn = reinterpret_cast<const char*> + (size == 32 ? lea_r10_insn_32 : lea_r10_insn_64); + const char* const lea_r11_insn = reinterpret_cast<const char*> + (size == 32 ? lea_r11_insn_32 : lea_r11_insn_64); + + const size_t cmp_insn_len = + (size == 32 ? sizeof(cmp_insn_32) : sizeof(cmp_insn_64)); + const size_t lea_r10_insn_len = + (size == 32 ? sizeof(lea_r10_insn_32) : sizeof(lea_r10_insn_64)); + const size_t lea_r11_insn_len = + (size == 32 ? sizeof(lea_r11_insn_32) : sizeof(lea_r11_insn_64)); + const size_t nop_len = (size == 32 ? 7 : 8); + // The function starts with a comparison of the stack pointer and a // field in the TCB. This is followed by a jump. // cmp %fs:NN,%rsp - if (this->match_view(view, view_size, fnoffset, "\x64\x48\x3b\x24\x25", 5) - && fnsize > 9) + if (this->match_view(view, view_size, fnoffset, cmp_insn, cmp_insn_len) + && fnsize > nop_len + 1) { // We will call __morestack if the carry flag is set after this // comparison. We turn the comparison into an stc instruction // and some nops. view[fnoffset] = '\xf9'; - this->set_view_to_nop(view, view_size, fnoffset + 1, 8); + this->set_view_to_nop(view, view_size, fnoffset + 1, nop_len); } // lea NN(%rsp),%r10 // lea NN(%rsp),%r11 else if ((this->match_view(view, view_size, fnoffset, - "\x4c\x8d\x94\x24", 4) + lea_r10_insn, lea_r10_insn_len) || this->match_view(view, view_size, fnoffset, - "\x4c\x8d\x9c\x24", 4)) + lea_r11_insn, lea_r11_insn_len)) && fnsize > 8) { // This is loading an offset from the stack pointer for a |