forked from Keelrleek/Harbor
re_lookup/re_disassemble show the calling convention read from the bytes
This commit is contained in:
1 parent
c7e678eacb
commit
ec210c019f
1 file changed
+28
@@ -39,6 +39,7 @@ class Reverse:
|
||||
self.imports_path = Path(config["imports"]) if config.get("imports") else None
|
||||
self.annotations = Path(config["annotations"]) if config.get("annotations") else None
|
||||
self.src = Path(config["src"]) if config.get("src") else None
|
||||
self.conventions_path = Path(config["conventions"]) if config.get("conventions") else None
|
||||
self._cache = {}
|
||||
|
||||
# ----------------------------------------------------------------- loading (cached by file mtime)
|
||||
@@ -162,6 +163,26 @@ class Reverse:
|
||||
raise HarborError(f"{target!r} is neither an address nor a known name")
|
||||
return addr
|
||||
|
||||
def convention(self, addr):
|
||||
"""The calling convention read from the bytes: register inputs (a dataflow pass) and the `ret N` cleanup."""
|
||||
if not self.conventions_path or not self.conventions_path.exists():
|
||||
return None
|
||||
module = self._cache.get("conventions_module")
|
||||
if module is None:
|
||||
import importlib.util
|
||||
spec = importlib.util.spec_from_file_location("harbor_conventions", self.conventions_path)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module)
|
||||
self._cache["conventions_module"] = module
|
||||
func = self.function_at(addr)
|
||||
if not func:
|
||||
return None
|
||||
result = module.analyse(self._bytes(), func[0], func[1])
|
||||
if not result:
|
||||
return None
|
||||
return {"summary": module.describe(result), "registers_in": result["registers_in"],
|
||||
"ret_pops": result["ret_pops"]}
|
||||
|
||||
# ----------------------------------------------------------------- tools
|
||||
def read(self, addr, count):
|
||||
data = self._bytes()
|
||||
@@ -192,6 +213,10 @@ class Reverse:
|
||||
lines = []
|
||||
if func and not max_bytes:
|
||||
lines.append(f"; {func[2] or 'unnamed'} 0x{func[0]:X}..0x{func[0] + func[1]:X} ({func[1]} bytes)")
|
||||
conv = self.convention(func[0])
|
||||
if conv:
|
||||
lines.append(f"; convention from the bytes: {conv['summary']}; registers in: "
|
||||
f"{', '.join(conv['registers_in']) or 'none'}; ret pops {conv['ret_pops']}")
|
||||
for ins in md.disasm(code, start):
|
||||
note = self._annotate(ins.op_str, ins.mnemonic, start, start + size)
|
||||
lines.append(f"{ins.address:08X} {ins.mnemonic:7} {ins.op_str}{(' ; ' + note) if note else ''}")
|
||||
@@ -261,6 +286,9 @@ class Reverse:
|
||||
func = self.function_at(addr)
|
||||
if func:
|
||||
out["function"] = {"start": f"0x{func[0]:X}", "size": func[1], "name": func[2]}
|
||||
conv = self.convention(func[0])
|
||||
if conv:
|
||||
out["convention_from_bytes"] = conv
|
||||
for table, key in (("names.csv", "names_row"), ("functions.csv", "functions_row"), ("globals.csv", "globals_row")):
|
||||
row = self._csv(table).get(addr)
|
||||
if row:
|
||||
|
||||
Reference in new issue
Block a user