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
4 changes: 2 additions & 2 deletions chb/app/CHVersion.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
chbversion: str = "0.3.0-20260218"
chbversion: str = "0.3.0-20260324"

minimum_required_chb_version = "0.6.0_20260122"
minimum_required_chb_version = "0.6.0_20260324"
22 changes: 22 additions & 0 deletions chb/bctypes/BCAttrParam.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ def __init__(
def is_int(self) -> bool:
return False

@property
def to_c_string(self) -> str:
return str(self)

def __str__(self) -> str:
return "bc-attrparam:" + self.tags[0]

Expand All @@ -96,6 +100,10 @@ def intvalue(self) -> int:
def is_int(self) -> bool:
return True

@property
def to_c_string(self) -> str:
return str(self.intvalue)

def __str__(self) -> str:
return "aint(" + str(self.intvalue) + ")"

Expand All @@ -114,6 +122,10 @@ def __init__(
def strvalue(self) -> str:
return self.bcd.string(self.args[0])

@property
def to_c_string(self) -> str:
return self.strvalue

def __str__(self) -> str:
return "astr(" + self.strvalue + ")"

Expand All @@ -136,6 +148,16 @@ def name(self) -> str:
def params(self) -> List["BCAttrParam"]:
return [self.bcd.attrparam(i) for i in self.args]

@property
def to_c_string(self) -> str:
if len(self.params) == 0:
return self.name
else:
return (
self.name + "("
+ ", ".join(p.to_c_string for p in self.params)
+ ")")

def __str__(self) -> str:
return (
"acons("
Expand Down
20 changes: 19 additions & 1 deletion chb/bctypes/BCAttribute.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ def params(self) -> List["BCAttrParam"]:
def is_volatile(self) -> bool:
return self.name == "volatile"

@property
def to_c_string(self) -> str:
return self.name + "(" + ", ".join(p.to_c_string for p in self.params) + ")"

def __str__(self) -> str:
return self.name + "(" + ", ".join(str(p) for p in self.params) + ")"

Expand All @@ -73,5 +77,19 @@ def __init__(
def attrs(self) -> List[BCAttribute]:
return [self.bcd.attribute(i) for i in self.args]

@property
def is_empty(self) -> bool:
return len(self.attrs) == 0

@property
def to_c_string(self) -> str:
return (
"__attribute__(("
+ "\n ".join(a.to_c_string for a in self.attrs)
+ "\n ))")

def __str__(self) -> str:
return ", ".join(str(a) for a in self.attrs)
return (
"__attribute__(("
+ ", ".join(str(a) for a in self.attrs)
+ "))" )
27 changes: 27 additions & 0 deletions chb/bctypes/BCDictionary.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,3 +290,30 @@ def f(ix: int, v: IT.IndexedTableValue) -> None:

self.compinfo_table.iter(f)
return "\n".join(lines)

def varinfo_table_to_string(self) -> str:
lines: List[str] = []

def f(ix: int, v: IT.IndexedTableValue) -> None:
lines.append(str(ix) + ": " + str(self.varinfo(ix)))

self.varinfo_table.iter(f)
return "\n".join(lines)

def varinfo_table_to_declarations(self) -> str:
lines: List[str] = []

def f(ix: int, v: IT.IndexedTableValue) -> None:
lines.append(self.varinfo(ix).to_c_string)

self.varinfo_table.iter(f)
return "\n\n".join(lines)

def attributes_table_to_string(self) -> str:
lines: List[str] = []

def f(ix: int, v: IT.IndexedTableValue) -> None:
lines.append(str(ix) + ": " + str(self.attributes(ix)))

self.attributes_table.iter(f)
return "\n".join(lines)
45 changes: 43 additions & 2 deletions chb/bctypes/BCVarInfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@
# SOFTWARE.
# ------------------------------------------------------------------------------

from typing import Any, cast, Dict, List, TYPE_CHECKING
from typing import Any, cast, Dict, List, Optional, TYPE_CHECKING

import chb.ast.ASTNode as AST

from chb.bctypes.BCAttribute import BCAttributes
from chb.bctypes.BCConverter import BCConverter
from chb.bctypes.BCDictionaryRecord import BCDictionaryRecord
from chb.bctypes.BCVisitor import BCVisitor
Expand Down Expand Up @@ -65,9 +66,44 @@ def vtype(self) -> "BCTyp":
def vparam(self) -> int:
return self.args[7]

@property
def attributes(self) -> Optional["BCAttributes"]:
return self.bcd.attributes(self.args[2])

def convert(self, converter: "BCConverter") -> AST.ASTVarInfo:
return converter.convert_varinfo(self)

@property
def to_c_string(self) -> str:
if self.vtype.is_array:
atype = cast("BCTypArray", self.vtype)
if atype.has_constant_size():
asize = atype.sizevalue
return (
str(atype.tgttyp)
+ " "
+ self.vname
+ "["
+ str(asize)
+ "];")
else:
return str(self.vtype) + " " + self.vname
elif self.vtype.is_function:
ftype = cast("BCTypFun", self.vtype)
if ftype.argtypes is not None:
argtypes = str(ftype.argtypes)
else:
argtypes = "()"
fattrs = self.attributes
if fattrs is not None and not fattrs.is_empty:
pfattrs = "\n" + fattrs.to_c_string
else:
pfattrs = ""
return (str(ftype.returntype) + " " + self.vname + argtypes + pfattrs) + ";"
else:
return str(self.vtype) + " " + self.vname + ";"


def __str__(self) -> str:
if self.vtype.is_array:
atype = cast("BCTypArray", self.vtype)
Expand All @@ -88,6 +124,11 @@ def __str__(self) -> str:
argtypes = str(ftype.argtypes)
else:
argtypes = "()"
return (str(ftype.returntype) + " " + self.vname + argtypes)
fattrs = self.attributes
if fattrs is not None:
pfattrs = " " + str(fattrs)
else:
pfattrs = ""
return (str(ftype.returntype) + " " + self.vname + argtypes + pfattrs)
else:
return str(self.vtype) + " " + self.vname
7 changes: 6 additions & 1 deletion chb/cmdline/AnalysisManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#
# Copyright (c) 2016-2020 Kestrel Technology LLC
# Copyright (c) 2020 Henny Sipma
# Copyright (c) 2021-2025 Aarno Labs LLC
# Copyright (c) 2021-2026 Aarno Labs LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
Expand Down Expand Up @@ -296,6 +296,7 @@ def analyze(
ignore_stable: bool = False,
save_asm: bool = False,
construct_all_functions: bool = False,
construct_signatures: bool = False,
mem: bool = False,
timeout: Optional[int] = None,
preamble_cutoff: int = 12) -> int:
Expand All @@ -310,6 +311,7 @@ def analyze(
timeout=timeout,
verbose=verbose,
construct_all_functions=construct_all_functions,
construct_signatures=construct_signatures,
collectdiagnostics=collectdiagnostics,
failonfunctionfailure=failonfunctionfailure,
preamble_cutoff=preamble_cutoff)
Expand Down Expand Up @@ -450,6 +452,7 @@ def _analyze_until_stable(
timeout: Optional[int] = None,
verbose: bool = False,
construct_all_functions: bool = False,
construct_signatures: bool = False,
collectdiagnostics: bool = False,
failonfunctionfailure: bool = False,
preamble_cutoff: int = 12) -> int:
Expand Down Expand Up @@ -546,6 +549,8 @@ def _analyze_until_stable(
chklogger.logger.debug("execute zip command %s", " ".join(zipcmd))
subprocess.call(zipcmd, stderr=subprocess.STDOUT, cwd=analysisdir)
fincmd = cmd + ["-collectdata"]
if construct_signatures:
fincmd = fincmd + ["-construct_signatures"]
if self.use_ssa:
fincmd = fincmd + ["-ssa"]
if self.no_varinvs:
Expand Down
5 changes: 5 additions & 0 deletions chb/cmdline/PatchResults.py
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,10 @@ def logicalva(self) -> str:
def is_trampoline(self) -> bool:
return self.patchkind == "Trampoline"

@property
def is_new_function(self) -> bool:
return self.patchkind == "NewFunction"

@property
def is_supported(self) -> bool:
return self.is_trampoline
Expand Down Expand Up @@ -431,6 +435,7 @@ def trampoline_addresses(self) -> List[Dict[str, str]]:
if e.case_fallthrough_jump is not None:
r["fallthrough-jump"] = e.case_fallthrough_jump
result.append(r)

return result


Expand Down
14 changes: 14 additions & 0 deletions chb/cmdline/chkx
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,10 @@ def parse() -> argparse.Namespace:
"--construct_all_functions",
action="store_true",
help="construct all functions even if not all functions are analyzed")
analyzecmd.add_argument(
"--construct_signatures",
action="store_true",
help="infer and construct function signatures for functions without them")
analyzecmd.add_argument(
"--collect_diagnostics",
action="store_true",
Expand Down Expand Up @@ -1752,6 +1756,16 @@ def parse() -> argparse.Namespace:
table_type.add_argument("xname", help="name of executable")
table_type.set_defaults(func=UCC.show_type_table)

# --- attributes ---
table_type = tableparsers.add_parser("attributes")
table_type.add_argument("xname", help="name of executable")
table_type.set_defaults(func=UCC.show_attributes_table)

# --- varinfo ---
table_type = tableparsers.add_parser("varinfo")
table_type.add_argument("xname", help="name of executable")
table_type.set_defaults(func=UCC.show_varinfo_table)

# --- compinfo ---
table_compinfo = tableparsers.add_parser("compinfo")
table_compinfo.add_argument("xname", help="name of executable")
Expand Down
50 changes: 50 additions & 0 deletions chb/cmdline/commandutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,7 @@ def analyzecmd(args: argparse.Namespace) -> NoReturn:
analyze_range_entry_points: List[str] = args.analyze_range_entry_points
gc_compact: int = args.gc_compact
construct_all_functions: bool = args.construct_all_functions
construct_signatures: bool = args.construct_signatures
show_function_timing: bool = args.show_function_timing
lineq_instr_cutoff: int = args.lineq_instr_cutoff
lineq_block_cutoff: int = args.lineq_block_cutoff
Expand Down Expand Up @@ -601,6 +602,7 @@ def analyzecmd(args: argparse.Namespace) -> NoReturn:
verbose=verbose,
save_asm=save_asm,
construct_all_functions=construct_all_functions,
construct_signatures=construct_signatures,
collectdiagnostics=collectdiagnostics,
failonfunctionfailure=failonfunctionfailure,
preamble_cutoff=preamble_cutoff)
Expand Down Expand Up @@ -2526,6 +2528,54 @@ def show_type_table(args: argparse.Namespace) -> NoReturn:
exit(0)


def show_attributes_table(args: argparse.Namespace) -> NoReturn:

# arguments
xname: str = args.xname

try:
(path, xfile) = get_path_filename(xname)
UF.check_analysis_results(path, xfile)
except UF.CHBError as e:
print(str(e.wrap()))
exit(1)

xinfo = XI.XInfo()
xinfo.load(path, xfile)

app = get_app(path, xfile, xinfo)

bcdictionary = app.bcdictionary

print(bcdictionary.attributes_table_to_string())

exit(0)


def show_varinfo_table(args: argparse.Namespace) -> NoReturn:

# arguments
xname: str = args.xname

try:
(path, xfile) = get_path_filename(xname)
UF.check_analysis_results(path, xfile)
except UF.CHBError as e:
print(str(e.wrap()))
exit(1)

xinfo = XI.XInfo()
xinfo.load(path, xfile)

app = get_app(path, xfile, xinfo)

bcdictionary = app.bcdictionary

print(bcdictionary.varinfo_table_to_declarations())

exit(0)


def show_compinfo_table(args: argparse.Namespace) -> NoReturn:

# arguments
Expand Down