Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ======================== solution.S
- .intel_syntax noprefix
- .section .note.GNU-stack
- .text
- # uint64_t Indirect.Call(
- # uint64_t (*rax)(uint64_t, uint64_t),
- # uint64_t (*rbx)(),
- # uint64_t (*rcx)()
- # );
- .global Indirect.Call
- Indirect.Call:
- // TODO: your code here.
- ret
- ======================== test.cpp
- #include <iostream>
- #include <cstdint>
- #include <cassert>
- extern uint64_t (*realH)();
- extern uint64_t (*realG)();
- extern "C" uint64_t GWrapper();
- extern "C" uint64_t HWrapper();
- extern "C" uint64_t IndirectCallWrapper(uint64_t (*f)(uint64_t, uint64_t),
- uint64_t (*g)(), uint64_t (*h)());
- extern "C" uint64_t ReadRSP();
- extern "C" uint64_t ReadRSP2(uint64_t, uint64_t);
- asm(R"(
- ReadRSP:
- ReadRSP2:
- mov rax, rsp
- ret
- )");
- int main() {
- {
- realG = []() -> uint64_t { return 456; };
- realH = []() -> uint64_t { return 123; };
- uint64_t result = IndirectCallWrapper(
- [](uint64_t a, uint64_t b) { return a + b; }, GWrapper, HWrapper);
- assert(result == 123 + 456);
- result = IndirectCallWrapper([](uint64_t a, uint64_t b) { return a & ~b; },
- HWrapper, GWrapper);
- assert(result == (123 & ~456));
- }
- {
- uint64_t result1 = IndirectCallWrapper(
- [](uint64_t a, uint64_t b) { return ((a & 15) << 4) | (b & 15); },
- ReadRSP, ReadRSP);
- {
- assert(result1 == (128 | 8) && "Stack of g or h is not aligned");
- }
- uint64_t result2 = IndirectCallWrapper(
- ReadRSP2, []() -> uint64_t { return 0; },
- []() -> uint64_t { return 456; });
- {
- assert((result2 & 15) == 8 && "Stack of f is not aligned");
- }
- }
- {
- constexpr uint64_t kValue1 = 0x0123456789ABCDEFull;
- constexpr uint64_t kValue2 = 0xF543861BECD7A209ull;
- uint64_t result =
- IndirectCallWrapper([](uint64_t a, uint64_t b) { return ~a & b; },
- []() { return kValue1; }, []() { return kValue2; });
- assert(result == (~kValue1 & kValue2));
- }
- std::cout << "All test passed.";
- }
- ======================== wrapper.S
- .intel_syntax noprefix
- .section .note.GNU-stack
- .section .rodata, "a", @progbits
- fmt:
- .asciz "Register %s was not preserved"
- #define REG_STR(reg) \
- s##reg: \
- .asciz #reg
- REG_STR(rax)
- REG_STR(rbx)
- REG_STR(rcx)
- REG_STR(rdx)
- REG_STR(rdi)
- REG_STR(rsi)
- REG_STR(rbp)
- REG_STR(r8)
- REG_STR(r9)
- REG_STR(r10)
- REG_STR(r11)
- REG_STR(r12)
- REG_STR(r13)
- REG_STR(r14)
- REG_STR(r15)
- #undef REG_STR
- .bss
- .global realG
- realG:
- .quad 0
- .global realH
- realH:
- .quad 0
- .macro Clobber
- mov rax, 123
- mov rcx, 124
- mov rdx, 125
- mov rsi, 126
- mov rdi, 127
- mov r8, 128
- mov r9, 129
- mov r10, 130
- mov r11, 131
- .endm
- .text
- .global GWrapper
- GWrapper:
- Clobber
- jmp [rip + realG]
- .global HWrapper
- HWrapper:
- Clobber
- jmp [rip + realH]
- .global IndirectCallWrapper
- IndirectCallWrapper:
- push rbx
- mov rbx, rsi
- mov rcx, rdx
- mov rax, rdi
- push rbx
- push rcx
- push rdx
- push rdi
- push rsi
- push rbp
- push r8
- push r9
- push r10
- push r12
- push r13
- push r14
- push r15
- push r11
- call Indirect.Call
- cmp r11, [rsp]
- jne .r11_mismatch
- add rsp, 8
- .macro CHECK_REG reg
- cmp \reg, [rsp]
- lea r11, [rip + s\reg]
- jne .mismatch
- add rsp, 8
- .endm
- CHECK_REG r15
- CHECK_REG r14
- CHECK_REG r13
- CHECK_REG r12
- CHECK_REG r10
- CHECK_REG r9
- CHECK_REG r8
- CHECK_REG rbp
- CHECK_REG rsi
- CHECK_REG rdi
- CHECK_REG rdx
- CHECK_REG rcx
- CHECK_REG rbx
- pop rbx
- ret
- .r11_mismatch:
- lea rdi, [rip + fmt]
- lea rsi, [rip + sr11]
- xor eax, eax
- call printf
- call abort
- .mismatch:
- lea rdi, [rip + fmt]
- mov rsi, r11
- and rsp, -16
- xor eax, eax
- call printf
- call abort
Advertisement
Add Comment
Please, Sign In to add comment