Skip to content

Commit c4225b6

Browse files
committed
Fix two problems with x86 extraction logic
Problem 1 was the real problem and is was just the compiler using a register to write a zero instead of an immediate. Problem 2 was a secondary problem where our simple extraction logic with symbols didn't match our more complex logic w/o symbols. This was due to a broken call pattern match utility that didn't properly detect the AABA call pattern. Testing done with local shared library. Extraction into proper unit tests will come in a follow on PR.
1 parent a5a9a9b commit c4225b6

1 file changed

Lines changed: 40 additions & 14 deletions

File tree

interpreter/luajit/extractor_x86.go

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,20 @@ which is a dynamic public symbol that should be in all binaries of LuaJIT includ
5252
func (x *x86Extractor) findOffsetsFromLuaClose(b []byte) (glref, curL uint64, err error) {
5353
b, _ = xh.SkipEndBranch(b)
5454
var greg x86asm.Reg
55+
var zeroReg x86asm.Reg
5556
for len(b) > 0 {
5657
var i x86asm.Inst
5758
i, err = x86asm.Decode(b, 64)
5859
if err != nil {
5960
return 0, 0, err
6061
}
62+
if i.Op == x86asm.XOR {
63+
a0, ok1 := i.Args[0].(x86asm.Reg)
64+
a1, ok2 := i.Args[1].(x86asm.Reg)
65+
if ok1 && ok2 && a0 == a1 {
66+
zeroReg = a0
67+
}
68+
}
6169
if i.Op == x86asm.MOV {
6270
if greg == 0 {
6371
a0, ok1 := i.Args[0].(x86asm.Reg)
@@ -68,10 +76,17 @@ func (x *x86Extractor) findOffsetsFromLuaClose(b []byte) (glref, curL uint64, er
6876
}
6977
} else {
7078
a0, ok1 := i.Args[0].(x86asm.Mem)
71-
a1, ok2 := i.Args[1].(x86asm.Imm)
72-
if ok1 && ok2 && sameReg(a0.Base, greg) && a1 == 0 {
73-
curL = uint64(a0.Disp)
74-
return glref, curL, nil
79+
if ok1 && sameReg(a0.Base, greg) {
80+
imm, ok2 := i.Args[1].(x86asm.Imm)
81+
if ok2 && imm == 0 {
82+
curL = uint64(a0.Disp)
83+
return glref, curL, nil
84+
}
85+
r1, ok2 := i.Args[1].(x86asm.Reg)
86+
if ok2 && sameReg(r1, zeroReg) {
87+
curL = uint64(a0.Disp)
88+
return glref, curL, nil
89+
}
7590
}
7691
// If Greg is dest error
7792
if r0, ok := i.Args[0].(x86asm.Reg); ok && sameReg(r0, greg) {
@@ -82,7 +97,7 @@ func (x *x86Extractor) findOffsetsFromLuaClose(b []byte) (glref, curL uint64, er
8297
}
8398
b = b[i.Len:]
8499
}
85-
return 0, 0, errors.New("offsets not found")
100+
return 0, 0, errors.New("find offsets from lua_close failed")
86101
}
87102

88103
// This is different in most builds and we need to get it from stripped binaries.
@@ -325,8 +340,10 @@ func findRipRelativeLea2ndArgTo2ndCall(b []byte, baseAddr, targetCall int64) (ui
325340
//nolint:gocritic
326341
func skipCallsAABA(b []byte, ip, baseAddr int64) ([]byte, int64, error) {
327342
var lastCall int64
343+
var acall int64
344+
// 3 Step process, 1 is find AA, 2 is find B and 3 is find A.
328345
step := 0
329-
for len(b) > 0 && step < 3 {
346+
for len(b) > 0 {
330347
i, err := x86asm.Decode(b, 64)
331348
if err != nil {
332349
return nil, 0, err
@@ -335,20 +352,29 @@ func skipCallsAABA(b []byte, ip, baseAddr int64) ([]byte, int64, error) {
335352
a0, ok := i.Args[0].(x86asm.Rel)
336353
if ok {
337354
callAddr := baseAddr + ip + int64(i.Len) + int64(a0)
338-
if lastCall == callAddr {
339-
// Found AA
340-
step++
341-
} else if step > 0 {
342-
step++
355+
if step == 0 && callAddr == lastCall {
356+
// Found potential AA
357+
step = 1
358+
acall = callAddr
359+
} else if step == 1 && callAddr != lastCall {
360+
// Found AAB
361+
step = 2
362+
} else if step == 2 && callAddr == acall {
363+
// Found AABA
364+
step = 3
365+
} else {
366+
// Found different pattern, reset
367+
step = 0
368+
acall = 0
343369
}
344370
lastCall = callAddr
345371
}
346372
}
347373
ip += int64(i.Len)
348374
b = b[i.Len:]
349-
}
350-
if step == 3 {
351-
return b, ip, nil
375+
if step == 3 {
376+
return b, ip, nil
377+
}
352378
}
353379
return nil, 0, errors.New("failed to find AABA call pattern")
354380
}

0 commit comments

Comments
 (0)