X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gold%2Fx86_64.cc;h=1d9d9209bf3ac9721b6fbc21e61136d7e831195e;hb=3af96c0d99dedab49d2b82b730c74c27ce99bba4;hp=114ebb081fd76275e0a11d5a9fe1bd31a9571a77;hpb=48bc218262da3784dd5258b774832d6b36afcf93;p=deliverable%2Fbinutils-gdb.git diff --git a/gold/x86_64.cc b/gold/x86_64.cc index 114ebb081f..1d9d9209bf 100644 --- a/gold/x86_64.cc +++ b/gold/x86_64.cc @@ -5472,26 +5472,49 @@ Target_x86_64::Relocate::tls_desc_gd_to_ie( { if (r_type == elfcpp::R_X86_64_GOTPC32_TLSDESC) { - // leaq foo@tlsdesc(%rip), %rax - // ==> movq foo@gottpoff(%rip), %rax + // LP64: leaq foo@tlsdesc(%rip), %rax + // ==> movq foo@gottpoff(%rip), %rax + // X32: rex leal foo@tlsdesc(%rip), %eax + // ==> rex movl foo@gottpoff(%rip), %eax tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, -3); tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 4); tls::check_tls(relinfo, relnum, rela.get_r_offset(), - view[-3] == 0x48 && view[-2] == 0x8d && view[-1] == 0x05); + (((view[-3] & 0xfb) == 0x48 + || (size == 32 && (view[-3] & 0xfb) == 0x40)) + && view[-2] == 0x8d + && (view[-1] & 0xc7) == 0x05)); view[-2] = 0x8b; const elfcpp::Elf_Xword addend = rela.get_r_addend(); Relocate_functions::pcrela32(view, value, addend, address); } else { - // call *foo@tlscall(%rax) - // ==> nop; nop + // LP64: call *foo@tlscall(%rax) + // ==> xchg %ax, %ax + // X32: call *foo@tlscall(%eax) + // ==> nopl (%rax) gold_assert(r_type == elfcpp::R_X86_64_TLSDESC_CALL); tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 2); + int prefix = 0; + if (size == 32 && view[0] == 0x67) + { + tls::check_range(relinfo, relnum, rela.get_r_offset(), + view_size, 3); + prefix = 1; + } tls::check_tls(relinfo, relnum, rela.get_r_offset(), - view[0] == 0xff && view[1] == 0x10); - view[0] = 0x66; - view[1] = 0x90; + view[prefix] == 0xff && view[prefix + 1] == 0x10); + if (prefix) + { + view[0] = 0x0f; + view[1] = 0x1f; + view[2] = 0x00; + } + else + { + view[0] = 0x66; + view[1] = 0x90; + } } } @@ -5511,27 +5534,51 @@ Target_x86_64::Relocate::tls_desc_gd_to_le( { if (r_type == elfcpp::R_X86_64_GOTPC32_TLSDESC) { - // leaq foo@tlsdesc(%rip), %rax - // ==> movq foo@tpoff, %rax + // LP64: leaq foo@tlsdesc(%rip), %rax + // ==> movq foo@tpoff, %rax + // X32: rex leal foo@tlsdesc(%rip), %eax + // ==> rex movl foo@tpoff, %eax tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, -3); tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 4); tls::check_tls(relinfo, relnum, rela.get_r_offset(), - view[-3] == 0x48 && view[-2] == 0x8d && view[-1] == 0x05); + (((view[-3] & 0xfb) == 0x48 + || (size == 32 && (view[-3] & 0xfb) == 0x40)) + && view[-2] == 0x8d + && (view[-1] & 0xc7) == 0x05)); + view[-3] = (view[-3] & 0x48) | ((view[-3] >> 2) & 1); view[-2] = 0xc7; - view[-1] = 0xc0; + view[-1] = 0xc0 | ((view[-1] >> 3) & 7); value -= tls_segment->memsz(); Relocate_functions::rela32(view, value, 0); } else { - // call *foo@tlscall(%rax) - // ==> nop; nop + // LP64: call *foo@tlscall(%rax) + // ==> xchg %ax, %ax + // X32: call *foo@tlscall(%eax) + // ==> nopl (%rax) gold_assert(r_type == elfcpp::R_X86_64_TLSDESC_CALL); tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 2); + int prefix = 0; + if (size == 32 && view[0] == 0x67) + { + tls::check_range(relinfo, relnum, rela.get_r_offset(), + view_size, 3); + prefix = 1; + } tls::check_tls(relinfo, relnum, rela.get_r_offset(), - view[0] == 0xff && view[1] == 0x10); - view[0] = 0x66; - view[1] = 0x90; + view[prefix] == 0xff && view[prefix + 1] == 0x10); + if (prefix) + { + view[0] = 0x0f; + view[1] = 0x1f; + view[2] = 0x00; + } + else + { + view[0] = 0x66; + view[1] = 0x90; + } } }