Skip to content

Commit cbcd2de

Browse files
committed
fix(ArchPcode): ret_offset being wrong for archs with different reg for metatypes
1 parent 5112840 commit cbcd2de

1 file changed

Lines changed: 27 additions & 10 deletions

File tree

archinfo/arch_pcode.py

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import logging
22
from typing import Union
3+
from xml.etree.ElementTree import Element
34

45
from .arch import Arch, Endness, Register
56
from .archerror import ArchError
@@ -96,16 +97,7 @@ def find_matching_cid(language, desired):
9697
archinfo_regs[sp_reg.lower()].alias_names += ("sp",)
9798

9899
# Get return offset
99-
proto_tags = cspec.find("default_proto")
100-
if proto_tags is not None and len(proto_tags) >= 1:
101-
proto_tag = proto_tags[0]
102-
output_tags = proto_tag.find("output")
103-
if output_tags is not None and len(output_tags) >= 1:
104-
output_tag = output_tags[0]
105-
output_register_tag = output_tag.find("register")
106-
if output_register_tag is not None:
107-
output_reg = output_register_tag.attrib["name"]
108-
ret_offset = RegisterOffset(ctx.registers[output_reg].offset)
100+
ret_offset = self.__get_ret_offset(cspec, ctx)
109101

110102
if sp_offset is None:
111103
log.warning("Unknown stack pointer register offset?")
@@ -154,3 +146,28 @@ def disasm(self, bytestring, addr=0, thumb=False):
154146
ctx.setVariableDefault("TMode", 1 if thumb else 0)
155147
instructions = ctx.disassemble(bytestring, addr, 0, len(bytestring), 0).instructions
156148
return "\n".join(f"{insn.addr.offset:#x}:\t{insn.mnem} {insn.body}" for insn in instructions)
149+
150+
@staticmethod
151+
def __get_ret_offset(cspec: Element, ctx: pypcode.Context):
152+
proto_tags = cspec.find("default_proto")
153+
if proto_tags is None or len(proto_tags) == 0:
154+
return RegisterOffset(0)
155+
156+
proto_tag = proto_tags[0]
157+
output_tags = proto_tag.find("output")
158+
if output_tags is None:
159+
return RegisterOffset(0)
160+
161+
output_pentries_tag = output_tags.findall("pentry")
162+
for pentry_tag in output_pentries_tag:
163+
if "metatype" in pentry_tag.attrib:
164+
continue
165+
166+
output_register_tag = pentry_tag.find("register")
167+
if output_register_tag is None:
168+
continue
169+
170+
output_reg = output_register_tag.attrib["name"]
171+
return RegisterOffset(ctx.registers[output_reg].offset)
172+
173+
return RegisterOffset(0)

0 commit comments

Comments
 (0)