[docs]classArchPcode(Arch):""" archinfo interface to pypcode architectures. Provides minimal mapping for architectural info like register file map, endianness, bit width, etc. """
[docs]def__init__(self,language:Union["pypcode.ArchLanguage",str]):ifnot_has_pypcode:raiseArchError("pypcode not installed")ifisinstance(language,str):language=self._get_language_by_id(language)assertisinstance(language,pypcode.ArchLanguage)self.name=language.idself.pcode_arch=language.idself.description=language.descriptionself.bits=int(language.size)self.endness={"little":Endness.LE,"big":Endness.BE}[language.endian]self.instruction_endness=self.endnessself.sizeof=({"short":16,"int":32,"long":64,"long long":64}ifself.bits==64else{"short":16,"int":32,"long":32,"long long":64})self.elf_tls=TLSArchInfo(1,8,[],[0],[],0,0)# Build registers listctx=pypcode.Context(language)archinfo_regs={rname.lower():Register(rname.lower(),r.size,r.offset)forrname,rinctx.registers.items()}# Get program counter registerpc_offset=Nonepc_tag=language.pspec.find("programcounter")iflanguage.pspecisnotNoneelseNoneifpc_tagisnotNone:pc_reg=pc_tag.attrib.get("register",None)ifpc_regisnotNone:# FIXME: Assumes RAM spacepc_offset=ctx.registers[pc_reg].offsetaliases={"pc","ip"}aliases.discard(pc_reg.lower())foraliasinaliases:archinfo_regs.pop(alias,None)archinfo_regs[pc_reg.lower()].alias_names=tuple(aliases)ifpc_offsetisNone:log.warning("Unknown program counter register offset?")pc_offset=0x80000000sp_offset=Noneret_offset=RegisterOffset(0)iflen(language.cspecs):deffind_matching_cid(language,desired):forcidinlanguage.cspecs:ifcid[0]==desired:returncidreturnNonecspec_id=(find_matching_cid(language,"default")orfind_matching_cid(language,"gcc")orlist(language.cspecs)[0])cspec=language.cspecs[cspec_id]# Get stack pointer registersp_tag=cspec.find("stackpointer")ifsp_tagisnotNone:sp_reg=sp_tag.attrib.get("register",None)ifsp_regisnotNone:# FIXME: Assumes RAM spacesp_offset=ctx.registers[sp_reg].offsetifsp_reg.lower()!="sp":if"sp"inarchinfo_regs:log.warning("Unexpected SP conflict")delarchinfo_regs["sp"]archinfo_regs[sp_reg.lower()].alias_names+=("sp",)# Get return offsetproto_tags=cspec.find("default_proto")ifproto_tagsisnotNoneandlen(proto_tags)>=1:proto_tag=proto_tags[0]output_tags=proto_tag.find("output")ifoutput_tagsisnotNoneandlen(output_tags)>=1:output_tag=output_tags[0]output_register_tag=output_tag.find("register")ifoutput_register_tagisnotNone:output_reg=output_register_tag.attrib["name"]ret_offset=RegisterOffset(ctx.registers[output_reg].offset)ifsp_offsetisNone:log.warning("Unknown stack pointer register offset?")sp_offset=0x80000008self.instruction_alignment=1self.ip_offset=RegisterOffset(pc_offset)self.sp_offset=RegisterOffset(sp_offset)self.bp_offset=RegisterOffset(sp_offset)self.ret_offset=RegisterOffset(ret_offset)self.register_list=list(archinfo_regs.values())self.initial_sp=(0x8000<<(self.bits-16))-1self.linux_name=""# FIXMEself.triplet=""# FIXME# TODO: Replace the following hardcoded function prologues by data sourced from patterns.xmlif"PowerPC:BE"inself.name:self.function_prologs={# stwu r1, xx(r1); mfspr rx, lrb"\x94\x21[\xc0-\xff][\x00\x10\x20\x30\x40\x50\x60\x70\x80\x90\xa0\xb0\xc0\xd0\xe0\xf0]"b"[\x7c-\x7f][\x08\x28\x48\x68\x88\xa8\xc8\xe8]\x02\xa6",}if"sparc:"inself.name.lower()andself.bits==32:self.branch_delay_slot=Truesuper().__init__(endness=self.endness,instruction_endness=self.instruction_endness)
@staticmethoddef_get_language_by_id(lang_id)->"pypcode.ArchLanguage":ifnot_has_pypcode:raiseArchError("pypcode not installed")forarchinpypcode.Arch.enumerate():forlanginarch.languages:iflang.id==lang_id:returnlangraiseArchError("Language not found")