动态翻译代码异常时目标CPU状态恢复

动态翻译器执行时如果出现异常,可如何确定异常位置对应的目标位置呢?

首先,执行语句:

tb = tb_find_pc(pc);

其中pc表示异常出现时宿主PC值,如果返回的tb不为NULL,则说明异常发生在动态翻译代码执行时。

为了恢复目标CPU的状态,需要使用cpu_restore_state函数。它与函数cpu_gen_code类似,但两者生成中间码时调用函数分别是gen_intermediate_codegen_intermediate_code_pc:

void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)

{

    gen_intermediate_code_internal(tb, 0, env);

}

void gen_intermediate_code_pc(CPUSPARCState * env, TranslationBlock * tb)

{

    gen_intermediate_code_internal(tb, 1, env);

}

gen_intermediate_code_pc函数在生成中间码时,多了下面的处理(sparc)

        if (spc) {//spc=1

            qemu_log("Search PC...\n");

            j = gen_opc_ptr - gen_opc_buf;

            if (lj < j) {//zhxc, 一条目标指令翻译后可能对应多个操作

                lj++;

                while (lj < j)

                    gen_opc_instr_start[lj++] = 0;

                gen_opc_pc[lj] = dc->pc;

                gen_opc_npc[lj] = dc->npc;

                gen_opc_instr_start[lj] = 1;

                gen_opc_icount[lj] = num_insns;

            }

        }

通过gen_opc_pcgen_opc_npc可以知道TB中每条目标指令对应的PCNPC值;

通过gen_opc_instr_start可以知道中间指令与目标指令的对应关系;

通过gen_opc_icount可以知道指令在TB中的位置;

如基本块中前两条指令时AB,指令分别对应23条中间指令,则

gen_opc_pc[0] = PC0;

gen_opc_npc[0] = PC0+4;

gen_opc_instr_start[0] = 1;

gen_opc_icount[0] = 0;

gen_opc_instr_start[1] = 0;

gen_opc_pc[2] = PC0+4;

gen_opc_npc[2] = PC0+8;

gen_opc_instr_start[2] = 1;

gen_opc_icount[2] = 1;

gen_opc_instr_start[3] = 0;

gen_opc_instr_start[4] = 0;

假设执行第3条中间码生成的宿主指令时出错,则下面语句返回j=3

j = tcg_gen_code_search_pc(s, (uint8_t *)tc_ptr, searched_pc - tc_ptr);

通过语句:

    while (gen_opc_instr_start[j] == 0)

        j--;

可以确定j=2,于是在gen_pc_load函数中可以确定发生出错时对应的目标码PC值。

void gen_pc_load(CPUState *env, TranslationBlock *tb,

                unsigned long searched_pc, int pc_pos, void *puc)

{

    target_ulong npc;

    env->pc = gen_opc_pc[pc_pos];

    npc = gen_opc_npc[pc_pos];

    if (npc == 1) {

        /* dynamic NPC: already stored */

    } else if (npc == 2) {

        /* jump PC: use 'cond' and the jump targets of the translation */

        if (env->cond) {

            env->npc = gen_opc_jump_pc[0];

        } else {

            env->npc = gen_opc_jump_pc[1];

        }

    } else {

        env->npc = npc;

    }

    /* flush pending conditional evaluations before exposing cpu state */

    if (CC_OP != CC_OP_FLAGS) {

        helper_compute_psr();

    }

}


你可能感兴趣的:(动态翻译代码异常时目标CPU状态恢复)