def build_hexagon_analysis_h( path: str = "./rizin/librz/analysis/arch/hexagon/hexagon_analysis.h", ) -> None: with open(path, "w+") as f: f.write(get_generation_warning_c_code()) with open("handwritten/hexagon_analysis_h/include.h") as include: set_pos_after_license(include) f.writelines(include.readlines()) log("hexagon_analysis.h written to {}".format(path))
def copy_tests() -> None: with open("handwritten/analysis-tests/hexagon") as f: with open("./rizin/test/db/analysis/hexagon", "w+") as g: set_pos_after_license(g) g.writelines(f.readlines()) with open("handwritten/asm-tests/hexagon") as f: with open("./rizin/test/db/asm/hexagon", "w+") as g: set_pos_after_license(g) g.writelines(f.readlines()) log("Copied test files to ./rizin/test/db/")
def build_asm_hexagon_c( path: str = "rizin/librz/asm/p/asm_hexagon.c") -> None: with open(path, "w+") as f: f.write(get_generation_warning_c_code()) with open("handwritten/asm_hexagon_c/include.c") as include: set_pos_after_license(include) f.writelines(include.readlines()) with open("handwritten/asm_hexagon_c/initialization.c") as init: set_pos_after_license(init) f.writelines(init.readlines()) log("asm_hexagon.c written to {}".format(path))
def build_hexagon_disas_c( self, path: str = "./rizin/librz/asm/arch/hexagon/hexagon_disas.c" ) -> None: # TODO Clean up this method indent = PluginInfo.LINE_INDENT var = PluginInfo.HEX_INSTR_VAR_SYNTAX with open(path, "w+") as dest: dest.write(get_generation_warning_c_code()) with open("handwritten/hexagon_disas_c/include.c") as include: set_pos_after_license(include) dest.writelines(include.readlines()) header = ( "int hexagon_disasm_instruction(ut32 hi_u32, HexInsn *hi, ut32 addr) {\n" + '{}char signed_imm[16] = "";\n'.format(indent) + "{}// DUPLEXES\n".format(indent) + "{}if ((({} >> 14) & 0x3) == 0) {{\n".format(indent, var) + "{}switch (((({} >> 29) & 0xF) << 1) | (({} >> 13) & 1)) {{\n". format(indent * 2, var, var)) dest.write(header) # Duplexes for c in range(0xF): # Class 0xf is reserved yet. dest.write("{}case 0x{:x}:\n".format(indent * 3, c)) for d_instr in self.duplex_instructions.values(): if d_instr.encoding.get_i_class() == c: dest.write( indent_code_block( d_instr.get_instruction_init_in_c(), 4)) dest.write("{}break;\n".format(indent * 4)) # Normal instructions # Brackets for switch, if dest.write("{}}}\n{}}}\n{}else {{\n".format( indent * 2, indent, indent)) dest.write("{}switch (({} >> 28) & 0xF) {{\n".format( indent * 2, var)) for c in range(0x10): dest.write("{}case 0x{:x}:\n".format(indent * 3, c)) for instr in self.normal_instructions.values(): if instr.encoding.get_i_class() == c: dest.write( indent_code_block( instr.get_instruction_init_in_c(), 4)) dest.write("{}break;\n".format(indent * 4)) # Closing brackets for switch, else, function dest.write("{}}}\n{}}}\n{}return 4;\n}}".format( indent * 2, indent, indent)) log("Hexagon instruction disassembler code written to: {}".format( path))
def build_hexagon_c( self, path: str = "./rizin/librz/asm/arch/hexagon/hexagon.c") -> None: indent = PluginInfo.LINE_INDENT with open(path, "w+") as dest: dest.write(get_generation_warning_c_code()) with open("handwritten/hexagon_c/include.c") as include: set_pos_after_license(include) dest.writelines(include.readlines()) dest.write("\n") reg_class: str for reg_class in self.hardware_regs: func_name = HardwareRegister.get_func_name_of_class(reg_class) function = "char* {}(int opcode_reg)".format(func_name) self.reg_resolve_decl.append(function + ";") dest.write("\n{} {{\n".format(function)) parsing_code = HardwareRegister.get_parse_code_reg_bits( reg_class, "opcode_reg") parsing_code = indent_code_block(parsing_code, 1) if parsing_code != "": dest.write("{}\n".format(parsing_code)) dest.write("{}switch (opcode_reg) {{\n".format(indent)) dest.write( '{}default:\n{}rz_warn_if_reached();\n{}return "<err>";\n'. format(indent * 2, indent * 3, indent * 3)) hw_reg: HardwareRegister for hw_reg in self.hardware_regs[reg_class].values(): dest.write('{}case {}:\n{}return "{}";\n'.format( indent * 2, hw_reg.enum_name, indent * 3, hw_reg.asm_name.upper(), )) dest.write("{}}}\n}}\n".format(indent)) with open("handwritten/hexagon_c/functions.c") as func: set_pos_after_license(func) dest.writelines(func.readlines()) dest.write("\n") log("hexagon.c written to: {}".format(path))
def build_hexagon_h( self, path: str = "./rizin/librz/asm/arch/hexagon/hexagon.h") -> None: indent = PluginInfo.LINE_INDENT general_prefix = PluginInfo.GENERAL_ENUM_PREFIX with open(path, "w+") as dest: dest.write(get_generation_warning_c_code()) dest.write("\n") dest.write(get_include_guard("hexagon.h")) with open("handwritten/hexagon_h/typedefs.h") as typedefs: set_pos_after_license(typedefs) dest.writelines(typedefs.readlines()) reg_class: str for reg_class in self.hardware_regs: dest.write("\ntypedef enum {\n") hw_reg: HardwareRegister for hw_reg in sorted(self.hardware_regs[reg_class].values(), key=lambda x: x.hw_encoding): alias = ",".join(hw_reg.alias) dest.write("{}{} = {},{}\n".format( indent, hw_reg.enum_name, hw_reg.hw_encoding, " // " + alias if alias != "" else "", )) dest.write("}} {}{}; // {}\n".format( general_prefix, HardwareRegister.register_class_name_to_upper(reg_class), reg_class, )) with open("handwritten/hexagon_h/macros.h") as macros: set_pos_after_license(macros) dest.writelines(macros.readlines()) dest.write("\n") if len(self.reg_resolve_decl) == 0: raise ImplementationException( "Register resolve declarations missing" "(They get generated together with hexagon.c)." "Please generate hexagon.c before hexagon.h") for decl in self.reg_resolve_decl: dest.write(decl + "\n") with open("handwritten/hexagon_h/declarations.h") as decl: set_pos_after_license(decl) dest.writelines(decl.readlines()) dest.write("#endif") log("hexagon.h written to: {}".format(path))
def build_hexagon_regs( self, path: str = "rizin/librz/analysis/p/analysis_hexagon.c") -> None: profile = self.get_alias_profile().splitlines(keepends=True) offset = 0 for hw_reg_classes in self.hardware_regs: if hw_reg_classes in [ "IntRegsLow8", "GeneralSubRegs", "GeneralDoubleLow8Regs", "ModRegs", ]: continue # Those registers would only be duplicates. hw_reg: HardwareRegister for hw_reg in self.hardware_regs[hw_reg_classes].values(): profile.append(hw_reg.get_reg_profile(offset) + "\n") offset += int((hw_reg.size / 8)) profile.append("\n") profile = profile[:-1] # Remove line breaks profile[-1] = profile[-1][:-1] + ";\n" # [:-1] to remove line break. with open(path, "w+") as f: f.write(get_generation_warning_c_code()) with open("handwritten/analysis_hexagon_c/include.c") as include: set_pos_after_license(include) f.writelines(include.readlines()) with open( "handwritten/analysis_hexagon_c/functions.c") as functions: set_pos_after_license(functions) f.writelines(functions.readlines()) f.write("\n") tmp = list() tmp.append("const char *p =\n") tmp += profile tmp = make_c_block( lines=tmp, begin="static bool set_reg_profile(RzAnalysis *analysis)", ret="return rz_reg_set_profile_string(analysis->reg, p);\n", ) f.writelines(tmp) f.write("\n") with open("handwritten/analysis_hexagon_c/initialization.c" ) as initialization: set_pos_after_license(initialization) f.writelines(initialization.readlines()) f.write("\n")
def build_hexagon_analysis_c( self, path: str = "./rizin/librz/analysis/arch/hexagon/hexagon_analysis.c" ) -> None: indent = PluginInfo.LINE_INDENT with open(path, "w+") as f: f.write(get_generation_warning_c_code()) with open("handwritten/hexagon_analysis_c/include.c") as include: set_pos_after_license(include) f.writelines(include.readlines()) f.write("\n") f.write( "int hexagon_analysis_instruction(HexInsn *hi, RzAnalysisOp *op) {\n" ) f.write("{}static ut32 hw_loop0_start = 0;\n".format(indent)) f.write("{}static ut32 hw_loop1_start = 0;\n\n".format(indent)) f.write("{}switch (hi->instruction) {{\n".format(indent)) default = "{}default:\n".format(indent * 2) default += ( "{}if (is_endloop01_instr(hi) && hi->pkt_info.last_insn) {{\n". format(indent * 3) + "{}op->type = RZ_ANALYSIS_OP_TYPE_CJMP;\n".format(indent * 4) + "{}op->fail = hw_loop0_start;\n".format(indent * 4) + "{}op->jump = hw_loop1_start;\n".format(indent * 4) + "{}hw_loop1_start = 0;\n".format(indent * 4) + "{}hw_loop0_start = 0;\n{}}}\n".format(indent * 4, indent * 3)) default += ( "{}else if (is_endloop0_instr(hi) && hi->pkt_info.last_insn) {{\n" .format(indent * 3) + "{}op->type = RZ_ANALYSIS_OP_TYPE_CJMP;\n".format(indent * 4) + "{}op->jump = hw_loop0_start;\n".format(indent * 4) + "{}hw_loop0_start = 0;\n{}}}\n".format(indent * 4, indent * 3)) default += ( "{}else if (is_endloop1_instr(hi) && hi->pkt_info.last_insn) {{\n" .format(indent * 3) + "{}op->type = RZ_ANALYSIS_OP_TYPE_CJMP;\n".format(indent * 4) + "{}op->jump = hw_loop1_start;\n".format(indent * 4) + "{}hw_loop1_start = 0;\n{}}}\n".format(indent * 4, indent * 3)) default += "{}break;\n".format(indent * 3) f.write(default) all_instr = [i for i in self.normal_instructions.values()] for i in self.duplex_instructions.values(): all_instr.append(i) i: Instruction for i in all_instr: if i.has_jump_target: f.write("{}case {}:\n".format(indent * 2, i.plugin_name)) f.write("{}// {}\n".format(indent * 3, i.syntax)) f.write("{}{}\n".format(indent * 3, i.get_rizin_op_type())) if i.has_imm_jmp_target(): index = i.get_jmp_operand_syntax_index() if index < 0: raise ImplementationException( "Not PC relative operand given. But the jump needs one." "{}".format(i.llvm_syntax)) f.write( "{}op->jump = op->addr + (st32) hi->ops[{}].op.imm;\n" .format(indent * 3, index)) if i.predicated: f.write( "{}op->fail = op->addr + op->size;\n".format( indent * 3)) if i.is_loop_begin: f.write("{}if (is_loop0_begin(hi)) {{\n".format( indent * 3) + "{}hw_loop0_start = op->jump;\n{}}}\n". format(indent * 4, indent * 3)) f.write("{}else if (is_loop1_begin(hi)) {{\n". format(indent * 3) + "{}hw_loop1_start = op->jump;\n{}}}\n". format(indent * 4, indent * 3)) f.write("{}break;\n".format(indent * 3, indent * 2)) f.write("{i}}}\n{i}return op->size;\n}}".format(i=indent)) log("hexagon_analysis.c written to: {}".format(path))