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

Bhushan Attarde Bhushan.Attarde at imgtec.com
Mon Mar 9 04:18:44 PDT 2015

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?

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)
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().

Please let me know if I am missing something.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20150309/bd4e8e92/attachment.html>

More information about the lldb-dev mailing list