Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion chb/app/CHVersion.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
chbversion: str = "0.3.0-20260418"
chbversion: str = "0.3.0-20260527"

minimum_required_chb_version = "0.6.0_20260407"
21 changes: 21 additions & 0 deletions chb/app/FunctionStackframe.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,27 @@ def stackoffset_gap(self, offset: int) -> Optional[int]:
else:
return None

def stackoffset_zero_write_extent(self, offset: int) -> int:
"""Returns the span from offset upward through consecutive zero-write-only size-4 slots.

Walks upward (toward less negative offsets) from offset + 4, collecting
size-4 slots whose accesses are all zero writes. Stops at the first slot
that is absent, has size != 4, has no accesses, or has any non-zero-write
access. Returns the total span: (stopping offset) - offset.
"""
current = offset + 4
while True:
slot = self.stackslot(current)
if slot is None or slot.size != 4:
break
accesses = self.accesses.get(current, [])
if not accesses:
break
if not all(acc.is_zero_write for (_, acc) in accesses):
break
current += 4
return current - offset

@property
def accesses(self) -> Dict[int, List[Tuple[str, "FnStackAccess"]]]:
if self._accesses is None:
Expand Down
29 changes: 29 additions & 0 deletions chb/cmdline/reportcmds.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
from chb.app.Function import Function
from chb.app.FunctionStackframe import FunctionStackframe
from chb.app.Instruction import Instruction
from chb.invariants.FnStackAccess import FnStackAccess
from chb.invariants.XConstant import XIntConst
from chb.mips.MIPSInstruction import MIPSInstruction
from chb.models.BTerm import BTerm, BTermArithmetic
Expand Down Expand Up @@ -1262,6 +1263,20 @@ def find_function_attribute(app: "AppAccess", dstarg_index: int, fname: str, ins

return intermediate_attribute

def _has_blockwrite_and_zero_stores_only(
accesses: List[Tuple[str, "FnStackAccess"]]) -> bool:
"""True if accesses contain a block-write and only zero-value stores otherwise."""
has_blockwrite = False
for (_, acc) in accesses:
if acc.is_block_write:
has_blockwrite = True
elif acc.is_zero_write:
pass
else:
return False
return has_blockwrite


def calculate_buffer_size(stackframe: "FunctionStackframe",
stack_offset: int,
instr: "Instruction") -> tuple[Optional[int], str]:
Expand Down Expand Up @@ -1302,6 +1317,20 @@ def calculate_buffer_size(stackframe: "FunctionStackframe",
+ "; replacing it by the size derived from the stacklayout",
str(instr), str(stack_offset))
sizeorigin = "stackframe-layout"
elif buffersize == 4:
slot_accesses = stackframe.accesses.get(stack_offset, [])
if _has_blockwrite_and_zero_stores_only(slot_accesses):
buffersize = stackframe.stackoffset_zero_write_extent(stack_offset)
if buffersize > 4:
chklogger.logger.info(
"Stackbuffer size for %s at offset %s: inferred %s "
+ "from zero-initialized slot sequence",
str(instr), str(stack_offset), str(buffersize))
sizeorigin = "zero-init-sequence"
else:
sizeorigin = "stackslot-access"
else:
sizeorigin = "stackslot-access"
else:
sizeorigin = "stackslot-access"

Expand Down
8 changes: 8 additions & 0 deletions chb/invariants/FnStackAccess.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ def is_block_read(self) -> bool:
def is_block_write(self) -> bool:
return False

@property
def is_zero_write(self) -> bool:
return False


@varregistry.register_tag("rs", FnStackAccess)
class FnStackRegisterSpill(FnStackAccess):
Expand Down Expand Up @@ -251,6 +255,10 @@ def value(self) -> "XXpr":
def is_store(self) -> bool:
return True

@property
def is_zero_write(self) -> bool:
return self.value.is_int_constant and self.value.is_zero

def __str__(self) -> str:
return (
"stack-store("
Expand Down