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

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
1
down vote

favorite
1












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.







share|improve this question

























    up vote
    1
    down vote

    favorite
    1












    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.







    share|improve this question























      up vote
      1
      down vote

      favorite
      1









      up vote
      1
      down vote

      favorite
      1






      1





      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.







      share|improve this question













      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.









      share|improve this question












      share|improve this question




      share|improve this question








      edited Jun 28 at 9:20
























      asked Jun 28 at 7:12









      puzzlestorage

      63




      63




















          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.






          share|improve this answer























          • 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










          Your Answer







          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "106"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: false,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );








           

          draft saved


          draft discarded


















          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






























          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.






          share|improve this answer























          • 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














          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.






          share|improve this answer























          • 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












          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.






          share|improve this answer















          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.







          share|improve this answer















          share|improve this answer



          share|improve this answer








          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
















          • 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












           

          draft saved


          draft discarded


























           


          draft saved


          draft discarded














          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













































































          Popular posts from this blog

          Peggy Mitchell

          Palaiologos

          The Forum (Inglewood, California)