Closed komorogrov closed 1 year ago
The trampoline JSON encoding is very low-level (machine code bytes) and there is no built-in assembler. However, here is a basic workflow for designing custom trampolines:
Firstly, design the trampoline as an ordinary assembly files, e.g., in a tmp.s
file define:
# Save registers:
lea -0x4000(%rsp),%rsp
push %rdi
push %rsi
push %rax
push %rcx
push %rdx
push %r11
# Setup and execute a SYS_write system call:
leaq .LasmStr(%rip),%rsi
mov $asmStrlen,%edx
mov $0x2,%edi # stderr
mov $0x1,%eax # SYS_write
syscall
# Restore registers:
pop %r11
pop %rdx
pop %rcx
pop %rax
pop %rsi
pop %rdi
lea 0x4000(%rsp),%rsp
Remember, if using this mode, it is up to you to correctly save and restore the CPU state. In this example, the trampoline is saving and restoring several registers to the stack (registers used/clobbered by the system call). This trampoline does not use any instructions that clobber the %rflags
register, so it does not need to be saved.
Next, compile the assembly into an object file (tmp.o
):
$ gcc -c tmp.s
Next, disassemble the object file to reveal the machine code:
$ objdump -d tmp.o
0: 48 8d a4 24 00 c0 ff lea -0x4000(%rsp),%rsp
7: ff
8: 57 push %rdi
9: 56 push %rsi
a: 50 push %rax
b: 51 push %rcx
c: 52 push %rdx
d: 41 53 push %r11
f: 48 8d 35 00 00 00 00 lea 0x0(%rip),%rsi # 0x16
16: ba 00 00 00 00 mov $0x0,%edx
1b: bf 02 00 00 00 mov $0x2,%edi
20: b8 01 00 00 00 mov $0x1,%eax
25: 0f 05 syscall
27: 41 5b pop %r11
29: 5a pop %rdx
2a: 59 pop %rcx
2b: 58 pop %rax
2c: 5e pop %rsi
2d: 5f pop %rdi
2e: 48 8d a4 24 00 40 00 lea 0x4000(%rsp),%rsp
35: 00
The machine byte values can be manually translated into the JSON trampoline format. For example, the first instruction has the machine code hex bytes (48 8d a4 24 00 c0 ff ff
) which corresponds to the JSON decimal bytes (72, 141, 164, 36, 0, 192, 255, 255
).
Note that the final JSON trampoline will need to be patched up:
$.LasmStr
) and constants ($asmStrLen
) into zeros (0x0
). When translating into JSON trampoline format, the zeros will need to be manually replaced with corresponding label/macro name.$instr
, $BREAK
, ..., etc.) will need to be manually crafted (see the docs) depending on what you want to do.It is possible to debug trampolines by passing the --trap-all
option to E9Tool and then running the rewritten binary using GDB. This will cause GDB to trap/break for each trampoline entry. You can view the disassembly using GDB's la a
command. Then you can step through this trampoline using GDB's si
or ni
commands.
OK, thank you very much. I get it.
It is a very great Job!
I met a problem.
The Document said that trampoline template is specified using a form of annotated machine code. If I want to use machine code to develop new plug-in features, how does machine code correspond to assembly language?
The follow example from your Programming Guide, but I wonder how the two correspond.