Skip to content
This repository has been archived by the owner on Feb 13, 2024. It is now read-only.

Commit

Permalink
Support older CPUs that do not have xsave
Browse files Browse the repository at this point in the history
Fixes #173, #161, #164 (Once binaries are rebuilt on other platforms,
which they will be in subsequent commits).
  • Loading branch information
Keno committed Nov 19, 2016
1 parent 42d8104 commit 7cfebf2
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 20 deletions.
36 changes: 32 additions & 4 deletions src/Hooking/Hooking.jl
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,8 @@ end

# For x86_64: The text section of jumpto-x86_64-macho.o minus one byte (retq)
# For powerpc64: Everything until ld %r0, UC_MCONTEXT_GREGS_PC(%r3)
const resume_length = Sys.ARCH == :x86_64 ? 0x6c : 0x128
const regular_resume_length = Sys.ARCH == :x86_64 ? 0x6c : 0x128
const legacy_resume_length = 0xaa

function hook_asm_template(hook_addr, target_addr; call = true)
diff = (target_addr - (hook_addr + 5))%Int32
Expand Down Expand Up @@ -405,16 +406,40 @@ if !haskey(ENV,"GALLIUM_REBUILDING_HOOKING")
const hooking_lib = joinpath(dirname(@__FILE__),string("hooking-",Sys.ARCH))
global __init__

const CPUID_GETFEATURES = 0x01
const CPUID_XSAVE_BIT = UInt(1) << 26
function legacy_cpu()
if Sys.ARCH == :x86_64
cpuinfo = Ref{NTuple{4, UInt32}}()
ccall(:jl_cpuid, Void, (Ref{NTuple{4, UInt32}}, UInt32), cpuinfo, CPUID_GETFEATURES)
return (cpuinfo[][3] & CPUID_XSAVE_BIT) == 0 # ecx & CPUID_XSAVE_BIT
else
# No legacy configuration on other architectures currently
return false
end
end


function __init__()
global resume
global thehook
global callback_rwx
global resume_instructions
global running_on_legacy_cpu
here = dirname(@__FILE__)
function resume(RC)
ccall((:hooking_jl_jumpto, hooking_lib),Void,(Ptr{UInt8},),pointer(RC.data))
end
theresume = cglobal((:hooking_jl_jumpto, hooking_lib), Ptr{UInt8})
running_on_legacy_cpu = legacy_cpu()
if legacy_cpu()
thehook = cglobal((:hooking_jl_savecontext_legacy, hooking_lib), Ptr{UInt8})
theresume = cglobal((:hooking_jl_jumpto_legacy, hooking_lib), Ptr{UInt8})
resume_length = legacy_resume_length
else
thehook = cglobal((:hooking_jl_savecontext, hooking_lib), Ptr{UInt8})
theresume = cglobal((:hooking_jl_jumpto, hooking_lib), Ptr{UInt8})
resume_length = regular_resume_length
end
resume_instructions = unsafe_wrap(Array, convert(Ptr{UInt8}, theresume),
(resume_length,), false)
# Allocate an RWX page for the callback return
Expand All @@ -441,7 +466,6 @@ if !haskey(ENV,"GALLIUM_REBUILDING_HOOKING")
thecallback = Base.cfunction(callback,Void,Tuple{Ptr{Void}})::Ptr{Void}
ccall((:hooking_jl_set_callback, hooking_lib), Void, (Ptr{Void},),
thecallback)
thehook = cglobal((:hooking_jl_savecontext, hooking_lib), Ptr{UInt8})
end
end

Expand Down Expand Up @@ -565,7 +589,11 @@ unhook(hook::Hook) = unhook(hook.addr)

@inline function getcontext()
RCnew, rcptr = aligned_xsave_RC()
ccall((:hooking_jl_simple_savecontext, hooking_lib),Void,(Ptr{UInt64},),rcptr)
if running_on_legacy_cpu
ccall((:hooking_jl_simple_savecontext_legacy, hooking_lib),Void,(Ptr{UInt64},),rcptr)
else
ccall((:hooking_jl_simple_savecontext, hooking_lib),Void,(Ptr{UInt64},),rcptr)
end
RC = X86_64.BasicRegs()
for i in X86_64.basic_regs
set_dwarf!(RC, i, RegisterValue{UInt64}(unsafe_load(Ptr{UInt64}(rcptr),i+1), (-1%UInt64)))
Expand Down
71 changes: 64 additions & 7 deletions src/Hooking/getcontext-x86_64-elf.s
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
# the address of the stack buffer as that function's first
# argument.

.text
.align 4,0x90
.globl hooking_jl_savecontext
hooking_jl_savecontext:
# We will use the gpregs saving code twice, once in the xsave code path and
# once in the legacy fxsave code path, make it a macro.

.macro SAVE_GPREGS
nop
pushq %rbp
movq %rsp, %rbp
Expand Down Expand Up @@ -39,6 +39,14 @@ movq %r12, UC_MCONTEXT_GREGS_R12(%rsp)
movq %r13, UC_MCONTEXT_GREGS_R13(%rsp)
movq %r14, UC_MCONTEXT_GREGS_R14(%rsp)
movq %r15, UC_MCONTEXT_GREGS_R15(%rsp)
.endm

.text
.align 4,0x90
.globl hooking_jl_savecontext
.type hooking_jl_savecontext, @function
hooking_jl_savecontext:
SAVE_GPREGS

# Save FP and SSE state (RFBM = 0b11)
movq $3, %rax
Expand All @@ -57,6 +65,7 @@ movq %rbx, 0x38+512+UC_MCONTEXT_SIZE(%rsp)

# The actual xsave
xsave UC_MCONTEXT_SIZE(%rsp)

movq %rsp, %rdi

# Align stack for call
Expand All @@ -65,11 +74,34 @@ pushq %rsi # Makes the debugger's life easier
movq hooking_jl_callback@GOTPCREL(%rip), %rax
jmpq *(%rax)


.text
.align 4,0x90
.globl hooking_jl_simple_savecontext
hooking_jl_simple_savecontext:
.globl hooking_jl_savecontext_legacy
.type hooking_jl_savecontext_legacy, @function
hooking_jl_savecontext_legacy:
SAVE_GPREGS

# Use fxsave for floating point state, and xmm0-7.
# Then, manually fill in xmm8-xmm15
fxsave UC_MCONTEXT_SIZE(%rsp)
movq %xmm8 , 287+UC_MCONTEXT_SIZE (%rsp)
movq %xmm9 , 287+UC_MCONTEXT_SIZE+0x08(%rsp)
movq %xmm10, 287+UC_MCONTEXT_SIZE+0x10(%rsp)
movq %xmm11, 287+UC_MCONTEXT_SIZE+0x18(%rsp)
movq %xmm12, 287+UC_MCONTEXT_SIZE+0x20(%rsp)
movq %xmm13, 287+UC_MCONTEXT_SIZE+0x28(%rsp)
movq %xmm14, 287+UC_MCONTEXT_SIZE+0x30(%rsp)
movq %xmm15, 287+UC_MCONTEXT_SIZE+0x38(%rsp)

movq %rsp, %rdi

# Align stack for call
subq $8, %rsp
pushq %rsi # Makes the debugger's life easier
movq hooking_jl_callback@GOTPCREL(%rip), %rax
jmpq *(%rax)

.macro SAVE_GPREGS_SIMPLE
nop
movq %rax, UC_MCONTEXT_GREGS_RAX(%rdi)
movq %rbx, UC_MCONTEXT_GREGS_RBX(%rdi)
Expand All @@ -90,6 +122,13 @@ movq %r14, UC_MCONTEXT_GREGS_R14(%rdi)
movq %r15, UC_MCONTEXT_GREGS_R15(%rdi)
movq (%rsp),%rsi
movq %rsi, UC_MCONTEXT_GREGS_RIP(%rdi) # store return address as rip
.endm

.text
.align 4,0x90
.globl hooking_jl_simple_savecontext
hooking_jl_simple_savecontext:
SAVE_GPREGS_SIMPLE

# Save FP and SSE state (RFBM = 0b11)
movq $3, %rax
Expand All @@ -111,4 +150,22 @@ xsave UC_MCONTEXT_SIZE(%rdi)

retq

.text
.align 4,0x90
.globl hooking_jl_simple_savecontext_legacy
hooking_jl_simple_savecontext_legacy:
SAVE_GPREGS_SIMPLE

fxsave UC_MCONTEXT_SIZE(%rdi)
movq %xmm8 , 287+UC_MCONTEXT_SIZE (%rdi)
movq %xmm9 , 287+UC_MCONTEXT_SIZE+0x08(%rdi)
movq %xmm10, 287+UC_MCONTEXT_SIZE+0x10(%rdi)
movq %xmm11, 287+UC_MCONTEXT_SIZE+0x18(%rdi)
movq %xmm12, 287+UC_MCONTEXT_SIZE+0x20(%rdi)
movq %xmm13, 287+UC_MCONTEXT_SIZE+0x28(%rdi)
movq %xmm14, 287+UC_MCONTEXT_SIZE+0x30(%rdi)
movq %xmm15, 287+UC_MCONTEXT_SIZE+0x38(%rdi)

retq

.section .note.GNU-stack,"",@progbits
Binary file modified src/Hooking/hooking-x86_64.so
Binary file not shown.
40 changes: 31 additions & 9 deletions src/Hooking/jumpto-x86_64-elf.s
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
# cpp jumpto-x86_64-elf.s | ~/julia-debugger/usr/bin/llvm-mc -filetype=obj - -o elfjump.o

.text
.align 4,0x90
.globl hooking_jl_jumpto
hooking_jl_jumpto:
nop
# Restore FP and SSE state (RFBM = 0b11)
movq $3, %rax
xor %rdx, %rdx
xrstor UC_MCONTEXT_SIZE(%rdi)
.macro RESTORE_GPREGS_AND_JMP
movq UC_MCONTEXT_GREGS_RSP(%rdi), %rax # rax holds new stack pointer
subq $16, %rax
movq %rax, UC_MCONTEXT_GREGS_RSP(%rdi)
Expand Down Expand Up @@ -40,5 +32,35 @@ movq UC_MCONTEXT_GREGS_R15(%rdi), %r15
movq UC_MCONTEXT_GREGS_RSP(%rdi), %rsp # cut back rsp to new location
pop %rdi # rdi was saved here earlier
ret # rip was saved here
.endm

.text
.align 4,0x90
.globl hooking_jl_jumpto
hooking_jl_jumpto:
nop
# Restore FP and SSE state (RFBM = 0b11)
movq $3, %rax
xor %rdx, %rdx
xrstor UC_MCONTEXT_SIZE(%rdi)

RESTORE_GPREGS_AND_JMP

.text
.align 4,0x90
.globl hooking_jl_jumpto_legacy
hooking_jl_jumpto_legacy:
nop
movq 287+UC_MCONTEXT_SIZE (%rdi), %xmm8
movq 287+UC_MCONTEXT_SIZE+0x08(%rdi), %xmm9
movq 287+UC_MCONTEXT_SIZE+0x10(%rdi), %xmm10
movq 287+UC_MCONTEXT_SIZE+0x18(%rdi), %xmm11
movq 287+UC_MCONTEXT_SIZE+0x20(%rdi), %xmm12
movq 287+UC_MCONTEXT_SIZE+0x28(%rdi), %xmm13
movq 287+UC_MCONTEXT_SIZE+0x30(%rdi), %xmm14
movq 287+UC_MCONTEXT_SIZE+0x38(%rdi), %xmm15
fxrstor UC_MCONTEXT_SIZE(%rdi)

RESTORE_GPREGS_AND_JMP

.section .note.GNU-stack,"",@progbits
1 change: 1 addition & 0 deletions src/Hooking/rebuild_hooklibs.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
ENV["GALLIUM_REBUILDING_HOOKING"] = "1"
using Gallium
function rebuild_lib(file, triple, oname)
contents = readstring(file)
Expand Down

0 comments on commit 7cfebf2

Please sign in to comment.