Skip to content
GitLab
Projects Groups Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
  • D dynamorio
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 1,467
    • Issues 1,467
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 44
    • Merge requests 44
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages and registries
    • Packages and registries
    • Package Registry
    • Infrastructure Registry
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • DynamoRIO
  • dynamorio
  • Issues
  • #3372
Closed
Open
Issue created Feb 12, 2019 by John F.X. Galea@johnfxgaleaContributor

DrReg EFLAG restoration problem.

Problem:

DrReg does not properly restore eflags when spilled in dead XAX.

Details

The sequence of the bug is as follows:

  1. DrReg spills eflags to XAX, where the XAX register is dead at this stage.
  2. App Instruction writes to XAX thus clobbering stored eflag content. Since XAX is dead, no eflag restoration occurs at this point.
  3. After the app instruction is executed, DrReg incorrectly restores clobbered (app) data to eflags.

I am running DynamoRIO against PHP, and as an example I am presenting the following log:

instrument_basic_block ******************

before instrumentation:
TAG  0xb733f6be
 +0    L3              58                   pop    eax
 +1    L3              8d 83 10 be ec ff    lea    eax, [ebx-0x001341f0]
 +7    L3              5a                   pop    edx
 +8    L3              50                   push   eax
 +9    L3              ff b3 4c 65 00 00    push   dword ptr [ebx+0x0000654c]
 +15   L3              e8 7e 72 03 00       call   0xb7376950
END 0xb733f6be
after instrumentation:
TAG  0xb733f6be
 +43   m4 @0x47c88f48  9f                   lahf
 +44   m4 @0x473a78b0  0f 90 c0             seto   al
 _<my instrumentation code>_
 +164  L3              58                   pop    eax
 _<my instrumentation code>_
 +356  m4 @0x473a5760  3c 81                cmp    al, 0x81
 +358  m4 @0x470abd9c  9e                   sahf
 +359  L3              8d 83 10 be ec ff    lea    eax, [ebx-0x001341f0]

Notice how flags are not restored at pop because eax is dead, but are so when lea is executed because at that point eax is indeed live.

Cause

Take a look at the following code in drreg_event_bb_insert_late:

 /* After each app write, update spilled app values: */
    for (reg = DR_REG_START_GPR; reg <= DR_REG_STOP_GPR; reg++) {
        if (pt->reg[GPR_IDX(reg)].in_use) {
            if (instr_writes_to_reg(inst, reg, DR_QUERY_INCLUDE_ALL) &&
                /* Don't bother if reg is dead beyond this write */
                (ops.conservative || pt->live_idx == 0 ||
                 drvector_get_entry(&pt->reg[GPR_IDX(reg)].live, pt->live_idx - 1) ==
                     REG_LIVE)) {
                uint tmp_slot = MAX_SPILLS;
                if (pt->aflags.xchg == reg) {
                    /* Bail on keeping the flags in the reg. */
                    drreg_move_aflags_from_reg(drcontext, bb, inst, pt, true);
                    continue;
                }
...

The issue is that the handling of eflags occurs only if XAX is live at pt->live_idx - 1. If XAX is dead, drreg_move_aflags_from_reg is not called.

I'll provide a fix

Assignee
Assign to
Time tracking