mirror of
https://github.com/waku-org/nwaku.git
synced 2025-01-28 15:46:33 +00:00
51 lines
1.3 KiB
Nim
51 lines
1.3 KiB
Nim
|
# Sourced from https://forum.nim-lang.org/t/9255#60617
|
||
|
|
||
|
import posix
|
||
|
|
||
|
type
|
||
|
Instr {.union.} = object
|
||
|
bytes: array[8, byte]
|
||
|
value: uint64
|
||
|
|
||
|
proc mockImpl(target, replacement: pointer) =
|
||
|
# YOLO who needs alignment
|
||
|
#doAssert (cast[ByteAddress](target) and ByteAddress(0x07)) == 0
|
||
|
var page = cast[pointer](cast[ByteAddress](target) and (not 0xfff))
|
||
|
doAssert mprotect(page, 4096, PROT_WRITE or PROT_EXEC) == 0
|
||
|
let rel = cast[ByteAddress](replacement) - cast[ByteAddress](target) - 5
|
||
|
var
|
||
|
instr =
|
||
|
Instr(
|
||
|
bytes: [
|
||
|
0xe9.byte,
|
||
|
(rel shr 0).byte,
|
||
|
(rel shr 8).byte,
|
||
|
(rel shr 16).byte,
|
||
|
(rel shr 24).byte,
|
||
|
0,
|
||
|
0,
|
||
|
0
|
||
|
]
|
||
|
)
|
||
|
cast[ptr uint64](target)[] = instr.value
|
||
|
doAssert mprotect(page, 4096, PROT_EXEC) == 0
|
||
|
|
||
|
# Note: Requires manual cleanup
|
||
|
# Usage Example:
|
||
|
# proc helloWorld(): string =
|
||
|
# "Hello, World!"
|
||
|
#
|
||
|
# echo helloWorld() # "Hello, World!"
|
||
|
#
|
||
|
# let backup = helloWorld
|
||
|
# mock(helloWorld):
|
||
|
# proc mockedHellWorld(): string =
|
||
|
# "Mocked Hello, World!"
|
||
|
# mockedMigrate
|
||
|
#
|
||
|
# echo helloWorld() # "Mocked Hello, World!"
|
||
|
#
|
||
|
# helloWorld = backup # Restore the original function
|
||
|
template mock*(target, replacement: untyped): untyped =
|
||
|
mockImpl(cast[pointer](target), cast[pointer](replacement))
|