2023-09-07 18:15:18 -07:00
|
|
|
#!/usr/bin/env python3
|
2021-12-28 09:01:14 -07:00
|
|
|
# pylint: disable=missing-class-docstring,no-self-use,line-too-long
|
2024-08-28 18:31:43 -07:00
|
|
|
from __future__ import annotations
|
|
|
|
|
|
2023-09-07 19:37:04 -07:00
|
|
|
__package__ = __package__ or "tests.sim" # pylint:disable=redefined-builtin
|
2023-09-07 17:49:51 -07:00
|
|
|
|
2018-08-16 20:27:34 +02:00
|
|
|
import logging
|
2021-02-12 15:11:02 -07:00
|
|
|
import os
|
|
|
|
|
import unittest
|
2018-08-16 20:27:34 +02:00
|
|
|
|
2026-06-02 14:48:07 -07:00
|
|
|
from archinfo import ArchAMD64, ArchSoot, all_arches
|
2018-08-16 20:27:34 +02:00
|
|
|
|
2026-06-02 14:48:07 -07:00
|
|
|
from angr import Project, SimState
|
|
|
|
|
from angr import sim_options as o
|
|
|
|
|
from angr.calling_conventions import DEFAULT_CC, SimCCUnknown, default_cc
|
2024-10-01 09:06:33 -07:00
|
|
|
from tests.common import bin_location
|
2023-09-07 19:37:04 -07:00
|
|
|
|
|
|
|
|
test_location = os.path.join(bin_location, "tests")
|
2018-08-16 20:27:34 +02:00
|
|
|
|
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TestStackAlignment(unittest.TestCase):
|
|
|
|
|
def test_alignment(self):
|
|
|
|
|
for arch in all_arches:
|
2023-09-20 19:51:52 -07:00
|
|
|
if arch.name in DEFAULT_CC and default_cc(arch.name, platform="Linux") is not SimCCUnknown:
|
2018-08-16 20:27:34 +02:00
|
|
|
# There is nothing to test for soot about stack alignment
|
2021-12-12 22:14:15 -07:00
|
|
|
if isinstance(arch, ArchSoot):
|
|
|
|
|
continue
|
|
|
|
|
log.info("Testing stack alignment for %s", arch.name)
|
2018-08-16 20:27:34 +02:00
|
|
|
st = SimState(arch=arch)
|
2023-09-20 19:51:52 -07:00
|
|
|
cc = default_cc(arch.name, platform="Linux")(arch=arch)
|
2018-08-16 20:27:34 +02:00
|
|
|
|
2021-12-28 09:01:14 -07:00
|
|
|
st.regs.sp = -1
|
2018-08-16 20:27:34 +02:00
|
|
|
|
|
|
|
|
# setup callsite with one argument (0x1337), "returning" to 0
|
2021-12-12 22:14:15 -07:00
|
|
|
cc.setup_callsite(st, 0, [0x1337], "void foo(int x)")
|
2018-08-16 20:27:34 +02:00
|
|
|
|
|
|
|
|
# ensure stack alignment is correct
|
2026-02-05 14:29:21 -07:00
|
|
|
assert st.solver.is_true((st.regs.sp + cc.STACKARG_SP_DIFF) % cc.STACK_ALIGNMENT == 0), (
|
|
|
|
|
f"non-zero stack alignment after setup_callsite for {cc}"
|
|
|
|
|
)
|
2018-08-16 20:27:34 +02:00
|
|
|
|
|
|
|
|
def test_sys_v_abi_compliance(self):
|
|
|
|
|
arch = ArchAMD64()
|
|
|
|
|
st = SimState(arch=arch)
|
2023-09-20 19:51:52 -07:00
|
|
|
cc = default_cc(arch.name, platform="Linux")(arch=arch)
|
2018-08-16 20:27:34 +02:00
|
|
|
|
|
|
|
|
st.regs.sp = -1
|
|
|
|
|
|
|
|
|
|
# setup callsite with one argument (0x1337), "returning" to 0
|
2021-12-28 09:01:14 -07:00
|
|
|
cc.setup_callsite(st, 0, [0x1337], "void foo(int x)")
|
|
|
|
|
|
2018-08-16 20:27:34 +02:00
|
|
|
# (rsp+8) must be aligned to 16 as required by System V ABI.
|
|
|
|
|
# ref: https://raw.githubusercontent.com/wiki/hjl-tools/x86-psABI/x86-64-psABI-1.0.pdf , page 18t
|
2021-12-28 09:01:14 -07:00
|
|
|
assert st.solver.is_true((st.regs.rsp + 8) % 16 == 0), "System V ABI calling convention violated!"
|
2018-08-16 20:27:34 +02:00
|
|
|
|
2021-02-12 15:11:02 -07:00
|
|
|
def test_initial_allocation(self):
|
|
|
|
|
# not strictly about alignment but it's about stack initialization so whatever
|
2023-09-07 19:37:04 -07:00
|
|
|
p = Project(os.path.join(test_location, "x86_64", "true"), auto_load_libs=False)
|
2021-02-12 15:11:02 -07:00
|
|
|
s = p.factory.entry_state(add_options={o.STRICT_PAGE_ACCESS})
|
2021-12-12 22:14:15 -07:00
|
|
|
s.memory.load(s.regs.sp - 0x10000, size=4)
|
2021-02-12 15:11:02 -07:00
|
|
|
|
2021-12-28 09:01:14 -07:00
|
|
|
|
2018-08-16 20:27:34 +02:00
|
|
|
if __name__ == "__main__":
|
|
|
|
|
unittest.main()
|