Details about implementation of CALL/RET instruction in QEMU (x86_64)

Clash Royale CLAN TAG#URR8PPP
up vote
1
down vote
favorite
In file target/i386/translate.c the CALL instruction (opcode 0xe8) has this implementation:
case 0xe8: /* call im */
if (dflag != MO_16)
tval = (int32_t)insn_get(env, s, MO_32);
else
tval = (int16_t)insn_get(env, s, MO_16);
next_eip = s->pc - s->cs_base;
tval += next_eip;
if (dflag == MO_16)
tval &= 0xffff;
else if (!CODE64(s))
tval &= 0xffffffff;
tcg_gen_movi_tl(cpu_T0, next_eip);
gen_push_v(s, cpu_T0);
gen_bnd_jmp(s);
gen_jmp(s, tval);
break;
The value in next_eip is saved by the following calls:
tcg_gen_movi_tl(cpu_T0, next_eip);
gen_push_v(s, cpu_T0);
But I can not find how this value (next_eip) is used in the RET implementation:
case 0xc3: /* ret */
ot = gen_pop_T0(s);
gen_pop_update(s, ot);
/* Note that gen_pop_T0 uses a zero-extending load. */
gen_op_jmp_v(cpu_T0);
gen_bnd_jmp(s);
gen_jr(s, cpu_T0);
break;
While i trace CALL implementation i see code where return adress is used:
void tcg_gen_op2(TCGOpcode opc, TCGArg a1, TCGArg a2)
TCGOp *op = tcg_emit_op(opc); // INDEX_op_movi_i64
op->args[0] = a1; // address of register
op->args[1] = a2; // **REAL RETURN ADDRESS**
But i can not find REAL RETURN ADDRESS while tracing RET implementation.
Can anyone tell me where exactly the RET instruction implementation uses the value in next_eip.
qemu
add a comment |Â
up vote
1
down vote
favorite
In file target/i386/translate.c the CALL instruction (opcode 0xe8) has this implementation:
case 0xe8: /* call im */
if (dflag != MO_16)
tval = (int32_t)insn_get(env, s, MO_32);
else
tval = (int16_t)insn_get(env, s, MO_16);
next_eip = s->pc - s->cs_base;
tval += next_eip;
if (dflag == MO_16)
tval &= 0xffff;
else if (!CODE64(s))
tval &= 0xffffffff;
tcg_gen_movi_tl(cpu_T0, next_eip);
gen_push_v(s, cpu_T0);
gen_bnd_jmp(s);
gen_jmp(s, tval);
break;
The value in next_eip is saved by the following calls:
tcg_gen_movi_tl(cpu_T0, next_eip);
gen_push_v(s, cpu_T0);
But I can not find how this value (next_eip) is used in the RET implementation:
case 0xc3: /* ret */
ot = gen_pop_T0(s);
gen_pop_update(s, ot);
/* Note that gen_pop_T0 uses a zero-extending load. */
gen_op_jmp_v(cpu_T0);
gen_bnd_jmp(s);
gen_jr(s, cpu_T0);
break;
While i trace CALL implementation i see code where return adress is used:
void tcg_gen_op2(TCGOpcode opc, TCGArg a1, TCGArg a2)
TCGOp *op = tcg_emit_op(opc); // INDEX_op_movi_i64
op->args[0] = a1; // address of register
op->args[1] = a2; // **REAL RETURN ADDRESS**
But i can not find REAL RETURN ADDRESS while tracing RET implementation.
Can anyone tell me where exactly the RET instruction implementation uses the value in next_eip.
qemu
add a comment |Â
up vote
1
down vote
favorite
up vote
1
down vote
favorite
In file target/i386/translate.c the CALL instruction (opcode 0xe8) has this implementation:
case 0xe8: /* call im */
if (dflag != MO_16)
tval = (int32_t)insn_get(env, s, MO_32);
else
tval = (int16_t)insn_get(env, s, MO_16);
next_eip = s->pc - s->cs_base;
tval += next_eip;
if (dflag == MO_16)
tval &= 0xffff;
else if (!CODE64(s))
tval &= 0xffffffff;
tcg_gen_movi_tl(cpu_T0, next_eip);
gen_push_v(s, cpu_T0);
gen_bnd_jmp(s);
gen_jmp(s, tval);
break;
The value in next_eip is saved by the following calls:
tcg_gen_movi_tl(cpu_T0, next_eip);
gen_push_v(s, cpu_T0);
But I can not find how this value (next_eip) is used in the RET implementation:
case 0xc3: /* ret */
ot = gen_pop_T0(s);
gen_pop_update(s, ot);
/* Note that gen_pop_T0 uses a zero-extending load. */
gen_op_jmp_v(cpu_T0);
gen_bnd_jmp(s);
gen_jr(s, cpu_T0);
break;
While i trace CALL implementation i see code where return adress is used:
void tcg_gen_op2(TCGOpcode opc, TCGArg a1, TCGArg a2)
TCGOp *op = tcg_emit_op(opc); // INDEX_op_movi_i64
op->args[0] = a1; // address of register
op->args[1] = a2; // **REAL RETURN ADDRESS**
But i can not find REAL RETURN ADDRESS while tracing RET implementation.
Can anyone tell me where exactly the RET instruction implementation uses the value in next_eip.
qemu
In file target/i386/translate.c the CALL instruction (opcode 0xe8) has this implementation:
case 0xe8: /* call im */
if (dflag != MO_16)
tval = (int32_t)insn_get(env, s, MO_32);
else
tval = (int16_t)insn_get(env, s, MO_16);
next_eip = s->pc - s->cs_base;
tval += next_eip;
if (dflag == MO_16)
tval &= 0xffff;
else if (!CODE64(s))
tval &= 0xffffffff;
tcg_gen_movi_tl(cpu_T0, next_eip);
gen_push_v(s, cpu_T0);
gen_bnd_jmp(s);
gen_jmp(s, tval);
break;
The value in next_eip is saved by the following calls:
tcg_gen_movi_tl(cpu_T0, next_eip);
gen_push_v(s, cpu_T0);
But I can not find how this value (next_eip) is used in the RET implementation:
case 0xc3: /* ret */
ot = gen_pop_T0(s);
gen_pop_update(s, ot);
/* Note that gen_pop_T0 uses a zero-extending load. */
gen_op_jmp_v(cpu_T0);
gen_bnd_jmp(s);
gen_jr(s, cpu_T0);
break;
While i trace CALL implementation i see code where return adress is used:
void tcg_gen_op2(TCGOpcode opc, TCGArg a1, TCGArg a2)
TCGOp *op = tcg_emit_op(opc); // INDEX_op_movi_i64
op->args[0] = a1; // address of register
op->args[1] = a2; // **REAL RETURN ADDRESS**
But i can not find REAL RETURN ADDRESS while tracing RET implementation.
Can anyone tell me where exactly the RET instruction implementation uses the value in next_eip.
qemu
edited Jun 28 at 9:20
asked Jun 28 at 7:12
puzzlestorage
63
63
add a comment |Â
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
0
down vote
The value in next_eip is popped from the stack:
ot = gen_pop_T0(s);
As a side-effect, this updates cpu_T0 which is then used for the jump; see the implementation of gen_pop_T0:
TCGMemOp d_ot = mo_pushpop(s, s->dflag);
gen_lea_v_seg(s, mo_stacksize(s), cpu_regs[R_ESP], R_SS, -1);
gen_op_ld_v(s, d_ot, cpu_T0, cpu_A0);
return d_ot;
This is how RET retrieves the value which was pushed by CALL:
tcg_gen_movi_tl(cpu_T0, next_eip);
gen_push_v(s, cpu_T0);
When interpreting a RET instruction, the emulator canâÂÂt rely on internal knowledge: it has to behave exactly as the RET instruction does, retrieving its return address from the stack. (In real-world code, there are many cases of RETs following a JMP with a manually-set-up stack rather than a CALL, or a CALL never resulting in a RET, or code changing the return address for the RET by changing the value on the stack.) This is what QEMUâÂÂs RET implementation does: it pops the return address from the stack (gen_pop_T0) and processes that.
Thanks for the quick response. As I understand it, gen_pop_T0 pops element of TCGTemp type. If I'm wrong, then please correct me. I can not find where in the structure of type TCGTemp the value of the return address is stored (next_eip).
â puzzlestorage
Jun 28 at 7:32
See my updated answer.
â Stephen Kitt
Jun 28 at 7:44
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
The value in next_eip is popped from the stack:
ot = gen_pop_T0(s);
As a side-effect, this updates cpu_T0 which is then used for the jump; see the implementation of gen_pop_T0:
TCGMemOp d_ot = mo_pushpop(s, s->dflag);
gen_lea_v_seg(s, mo_stacksize(s), cpu_regs[R_ESP], R_SS, -1);
gen_op_ld_v(s, d_ot, cpu_T0, cpu_A0);
return d_ot;
This is how RET retrieves the value which was pushed by CALL:
tcg_gen_movi_tl(cpu_T0, next_eip);
gen_push_v(s, cpu_T0);
When interpreting a RET instruction, the emulator canâÂÂt rely on internal knowledge: it has to behave exactly as the RET instruction does, retrieving its return address from the stack. (In real-world code, there are many cases of RETs following a JMP with a manually-set-up stack rather than a CALL, or a CALL never resulting in a RET, or code changing the return address for the RET by changing the value on the stack.) This is what QEMUâÂÂs RET implementation does: it pops the return address from the stack (gen_pop_T0) and processes that.
Thanks for the quick response. As I understand it, gen_pop_T0 pops element of TCGTemp type. If I'm wrong, then please correct me. I can not find where in the structure of type TCGTemp the value of the return address is stored (next_eip).
â puzzlestorage
Jun 28 at 7:32
See my updated answer.
â Stephen Kitt
Jun 28 at 7:44
add a comment |Â
up vote
0
down vote
The value in next_eip is popped from the stack:
ot = gen_pop_T0(s);
As a side-effect, this updates cpu_T0 which is then used for the jump; see the implementation of gen_pop_T0:
TCGMemOp d_ot = mo_pushpop(s, s->dflag);
gen_lea_v_seg(s, mo_stacksize(s), cpu_regs[R_ESP], R_SS, -1);
gen_op_ld_v(s, d_ot, cpu_T0, cpu_A0);
return d_ot;
This is how RET retrieves the value which was pushed by CALL:
tcg_gen_movi_tl(cpu_T0, next_eip);
gen_push_v(s, cpu_T0);
When interpreting a RET instruction, the emulator canâÂÂt rely on internal knowledge: it has to behave exactly as the RET instruction does, retrieving its return address from the stack. (In real-world code, there are many cases of RETs following a JMP with a manually-set-up stack rather than a CALL, or a CALL never resulting in a RET, or code changing the return address for the RET by changing the value on the stack.) This is what QEMUâÂÂs RET implementation does: it pops the return address from the stack (gen_pop_T0) and processes that.
Thanks for the quick response. As I understand it, gen_pop_T0 pops element of TCGTemp type. If I'm wrong, then please correct me. I can not find where in the structure of type TCGTemp the value of the return address is stored (next_eip).
â puzzlestorage
Jun 28 at 7:32
See my updated answer.
â Stephen Kitt
Jun 28 at 7:44
add a comment |Â
up vote
0
down vote
up vote
0
down vote
The value in next_eip is popped from the stack:
ot = gen_pop_T0(s);
As a side-effect, this updates cpu_T0 which is then used for the jump; see the implementation of gen_pop_T0:
TCGMemOp d_ot = mo_pushpop(s, s->dflag);
gen_lea_v_seg(s, mo_stacksize(s), cpu_regs[R_ESP], R_SS, -1);
gen_op_ld_v(s, d_ot, cpu_T0, cpu_A0);
return d_ot;
This is how RET retrieves the value which was pushed by CALL:
tcg_gen_movi_tl(cpu_T0, next_eip);
gen_push_v(s, cpu_T0);
When interpreting a RET instruction, the emulator canâÂÂt rely on internal knowledge: it has to behave exactly as the RET instruction does, retrieving its return address from the stack. (In real-world code, there are many cases of RETs following a JMP with a manually-set-up stack rather than a CALL, or a CALL never resulting in a RET, or code changing the return address for the RET by changing the value on the stack.) This is what QEMUâÂÂs RET implementation does: it pops the return address from the stack (gen_pop_T0) and processes that.
The value in next_eip is popped from the stack:
ot = gen_pop_T0(s);
As a side-effect, this updates cpu_T0 which is then used for the jump; see the implementation of gen_pop_T0:
TCGMemOp d_ot = mo_pushpop(s, s->dflag);
gen_lea_v_seg(s, mo_stacksize(s), cpu_regs[R_ESP], R_SS, -1);
gen_op_ld_v(s, d_ot, cpu_T0, cpu_A0);
return d_ot;
This is how RET retrieves the value which was pushed by CALL:
tcg_gen_movi_tl(cpu_T0, next_eip);
gen_push_v(s, cpu_T0);
When interpreting a RET instruction, the emulator canâÂÂt rely on internal knowledge: it has to behave exactly as the RET instruction does, retrieving its return address from the stack. (In real-world code, there are many cases of RETs following a JMP with a manually-set-up stack rather than a CALL, or a CALL never resulting in a RET, or code changing the return address for the RET by changing the value on the stack.) This is what QEMUâÂÂs RET implementation does: it pops the return address from the stack (gen_pop_T0) and processes that.
edited Jun 28 at 7:43
answered Jun 28 at 7:20
Stephen Kitt
139k22299361
139k22299361
Thanks for the quick response. As I understand it, gen_pop_T0 pops element of TCGTemp type. If I'm wrong, then please correct me. I can not find where in the structure of type TCGTemp the value of the return address is stored (next_eip).
â puzzlestorage
Jun 28 at 7:32
See my updated answer.
â Stephen Kitt
Jun 28 at 7:44
add a comment |Â
Thanks for the quick response. As I understand it, gen_pop_T0 pops element of TCGTemp type. If I'm wrong, then please correct me. I can not find where in the structure of type TCGTemp the value of the return address is stored (next_eip).
â puzzlestorage
Jun 28 at 7:32
See my updated answer.
â Stephen Kitt
Jun 28 at 7:44
Thanks for the quick response. As I understand it, gen_pop_T0 pops element of TCGTemp type. If I'm wrong, then please correct me. I can not find where in the structure of type TCGTemp the value of the return address is stored (next_eip).
â puzzlestorage
Jun 28 at 7:32
Thanks for the quick response. As I understand it, gen_pop_T0 pops element of TCGTemp type. If I'm wrong, then please correct me. I can not find where in the structure of type TCGTemp the value of the return address is stored (next_eip).
â puzzlestorage
Jun 28 at 7:32
See my updated answer.
â Stephen Kitt
Jun 28 at 7:44
See my updated answer.
â Stephen Kitt
Jun 28 at 7:44
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f452365%2fdetails-about-implementation-of-call-ret-instruction-in-qemu-x86-64%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password