[lldb-dev] Emulating load/restore register instructions in MIPS assembly profiler

Greg Clayton gclayton at apple.com
Mon Mar 9 13:17:05 PDT 2015


> On Mar 9, 2015, at 4:18 AM, Bhushan Attarde <bhushan.attarde at imgtec.com> wrote:
> 
> I am working on assembly profiler for MIPS using EmulateInstruction.
>  
> I have set the ContextType to eContextPopRegisterOffStack in the function which emulates  “ld    ra,40(sp)”
> (i.e. load/restore ra from stack) instruction.
>  
> 0xffffffff802009a4 <bar>:
> 0xffffffff802009a4:  67bdffd0   daddiu     sp,sp,-48
> 0xffffffff802009a8:  ffbf0028   sd   ra,40(sp)    -----> store return address
> 0xffffffff802009ac:  ffbe0020   sd   s8,32(sp)
> 0xffffffff802009b0:  03a0f02d   move s8,sp
> <..end of prologue...>
> <..some other instructions...>
> <..start of epilogue...>
> 0xffffffff802009f4:  03c0e82d   move sp,s8
> 0xffffffff802009f8:  dfbf0028   ld   ra,40(sp)    ------> restore return address
> 0xffffffff802009fc:  dfbe0020   ld   s8,32(sp)
> 0xffffffff80200a00:  67bd0030   daddiu     sp,sp,48
> 0xffffffff80200a04:  03e00008   jr   ra
> 0xffffffff80200a08:  00000000   nop
>  
> With this setting, the unwinder fails when we try to unwind from  0xffffffff802009fc.
> The call sequence is main()->foo()->bar() however,  backtrace displays only current frame.
> ----------------------------------------
> (lldb) bt
> * thread #1: tid = 0x0001, 0xffffffff802009fc a.out_64`bar(p=4) + 88 at a.c:30, stop reason = breakpoint 1.1
>   * frame #0: 0xffffffff802009fc a.out_64`bar(p=4) + 88 at a.c:30
> ---------------------------------------
>  
> Below is a part of generated log:
> --------------------------------------------------------------------------------------
> th1/fr0 0xffffffff802009fc: CFA=sp+48 => fp=[CFA-16] ra= <same> pc=[CFA-8]
>  
> th1/fr0 CFA is 0xffffffff800fff60: Register sp (29) contents are 0xffffffff800fff30, offset is 48
> th1/fr0 initialized frame current pc is 0xffffffff802009fc cfa is 0xffffffff800fff60 using EmulateInstructionMIPS64 UnwindPlan
> th1/fr0 requested caller's saved PC but this UnwindPlan uses a RA reg; getting ra (31) instead
> th1/fr0 supplying caller's saved ra (31)'s location using EmulateInstructionMIPS64 UnwindPlan
> th1/fr0 could not supply caller's ra (31) location, IsSame
> th1/fr1 could not get pc value
> Frame 1 invalid RegisterContext for this frame, stopping stack walk
> th1 Unwind of this thread is complete.
> --------------------------------------------------------------------------------------
>  
> Here we just need to tell the unwinder that the register has been restored and take this register from live register context.
> Which ContextType to use in such case?
>  

It seems like this is what is being done in UnwindAssemblyInstEmulation::WriteRegister (...):


        case EmulateInstruction::eContextPopRegisterOffStack:
            {
                const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
                if (reg_num != LLDB_INVALID_REGNUM)
                {
                    m_curr_row->SetRegisterLocationToSame (reg_num, must_replace);
                    m_curr_row_modified = true;
                    m_curr_insn_restored_a_register = true;
                }
            }
            break;



> 1. There exists similar ContextType - eContextRegisterLoad, but it is unimplemented (just breaks out and does nothing) in UnwindAssemblyInstEmulation::WriteRegister().
>    So will it be a good option to implement eContextRegisterLoad and set the register location to itself using SetRegisterLocationToRegister (reg_num, reg_num, true)
>    OR
> 2. Add new ContextType say eContextRegisterRestore to EmulateInstruction class and implement it in UnwindAssemblyInstEmulation::WriteRegister().
>    
> Also, consider location of pc if we are restoring the return address register.
> This is similar to how eContextPushRegisterOnStack handles return address register in UnwindAssemblyInstEmulation::WriteMemory().


If all goes well it seems like he code in UnwindAssemblyInstEmulation::WriteRegister() should be setting the register to be in the register itself. Can you step through this code and make sure we are happy with all of the register numbers?

Greg






More information about the lldb-dev mailing list