Yeah, it's incorrectly grabbing the stack pointer reg number (31) from the Rn 
bits and using that as the register # being saved, instead of the Rt and Rt2 
register numbers, and saying that v31 is being pushed twice.  It's an easy bug 
in EmulateInstructionARM64::EmulateLDPSTP but fixing that just presents us with 
the next problem so I haven't fixed it.

When I connect to debugserver on an arm64 device, it tells lldb about the 
pseudo regs on the device, like

  <reg name="x0" regnum="0" offset="0" bitsize="64" group="general" 
altname="arg1" group_id="1" ehframe_regnum="0" dwarf_regnum="0" generic="arg1" 
invalidate_regnums="0,34"/>

  <reg name="w0" regnum="34" offset="0" bitsize="32" group="general" 
group_id="1" value_regnums="0" invalidate_regnums="0,34"/>

  <reg name="v0" regnum="63" offset="268" bitsize="128" group="vector" 
type="float" altname="q0" encoding="vector" format="vector-uint8" group_id="2" 
dwarf_regnum="64" invalidate_regnums="63,129,97"/>

  <reg name="s0" regnum="97" offset="268" bitsize="32" group="float" 
type="float" encoding="ieee754" format="float" group_id="2" value_regnums="63" 
invalidate_regnums="63,129,97"/>

  <reg name="d0" regnum="129" offset="268" bitsize="64" group="float" 
type="float" encoding="ieee754" format="float" group_id="2" value_regnums="63" 
invalidate_regnums="63,129,97"/>


(this is the reply to the "qXfer:features:read:target.xml" packet that lldb 
sends to debugserver at the startup of the debug session) so the user can refer 
to these by name:

(lldb) reg read -f x s0
      s0 = 0x404e809d
(lldb) reg read -f x d0
      d0 = 0x41bdaf19404e809d
(lldb) reg read -f x v0
      v0 = 0x000000000000000041bdaf19404e809d
(lldb) 


J

> On Oct 12, 2016, at 6:23 PM, Tamas Berghammer <tbergham...@google.com> wrote:
> 
> I am a bit surprised that we don't define the smaller floating point 
> registers on AArch64 the same way we do it on x86/x86_64/Arm (have no idea 
> about MIPS) and I would consider this as a bug what we should fix (will gave 
> it a try when I have a few free cycles) because currently it is very 
> difficult to get a 64bit double value out of the data we are displaying.
> 
> Considering the fact that based on the ABI only the bottom 64bit have to be 
> saved I start to like the idea of teaching our unwinder about the smaller 
> floating point registers because that will mean that we can inspect float and 
> double variables from the parent stack frame while we never show some 
> corrupted data for variables occupying the full 128 bit vector register.
> 
> "...the unwind plan generated currently records this as v31 being saved...": 
> I don't understand this part. The code never references v31 nor d31 so if the 
> unwind plan records it as we saved v31 then something is clearly wrong there. 
> Does it treat all d0-d31 register as v31 because of some instruction decoding 
> reason?
> 
> Tamas
> 
> On Wed, Oct 12, 2016 at 4:30 PM Jason Molenda <jmole...@apple.com> wrote:
> Hi Tamas, sorry for that last email being a mess, I was doing something else 
> while writing it and only saw how unclear it was after I sent it.  You 
> understood everything I was trying to say.
> 
> I looked at the AAPCS64 again.  It says v8-v15 are callee saved, but says, 
> "Additionally, only the bottom 64-bits of each value stored in v8-v15 need to 
> be preserved[1]; it is the responsibility of the caller to preserve larger 
> values." so we're never going to have a full 128-bit value that we can get 
> off the stack (for targets following this ABI).
> 
> DWARF can get away with only defining register numbers for v0-v31 because 
> their use in DWARF always includes a byte size.  Having lldb register numbers 
> and using that numbering scheme instead of DWARF is an interesting one.  It 
> looks like all of the arm64 targets are using the definitions from 
> Plugins/Process/Utility/RegisterInfos_arm64.h.  It also only defines v0-v31 
> but the x86_64 RegisterInfos file defines pseudo registers ("eax") which are 
> a subset of real registers ("rax") - maybe we could do something like that.
> 
> I'm looking at this right now, but fwiw I wrote a small C program that uses 
> enough fp registers that the compiler will spill all of the preserved 
> registers (d8-d15) when I compile it with clang and -Os.  I'll use this for 
> testing
> 
> 
> 
> I get a prologue like
> 
> a.out`foo:
> a.out[0x100007a08] <+0>:   0x6dba3bef   stp    d15, d14, [sp, #-96]!
> a.out[0x100007a0c] <+4>:   0x6d0133ed   stp    d13, d12, [sp, #16]
> a.out[0x100007a10] <+8>:   0x6d022beb   stp    d11, d10, [sp, #32]
> a.out[0x100007a14] <+12>:  0x6d0323e9   stp    d9, d8, [sp, #48]
> a.out[0x100007a18] <+16>:  0xa9046ffc   stp    x28, x27, [sp, #64]
> a.out[0x100007a1c] <+20>:  0xa9057bfd   stp    x29, x30, [sp, #80]
> a.out[0x100007a20] <+24>:  0x910143fd   add    x29, sp, #80              ; =80
> 
> 
> and the unwind plan generated currently records this as v31 being saved in 
> the first instruction and ignores the others (because that reg has already 
> been saved).  That's the easy bug - but it's a good test case that I'll strip 
> down into a unit test once we get this figured out.
> 
> 
> J
> 
> 
> > On Oct 12, 2016, at 2:15 PM, Tamas Berghammer <tbergham...@google.com> 
> > wrote:
> >
> > Hi Jason,
> >
> > Thank you for adding unit test for this code. I think the current 
> > implementation doesn't fail terribly on 16 vs 32 byte stack alignment 
> > because we use the "opc" from the instruction to calculate the write back 
> > address (to adjust the SP) so having the wrong size of the register won't 
> > effect that part.
> >
> > Regarding the issue about s0/d0/v0 I don't have a perfect solution but here 
> > are some ideas:
> > * Use a different register numbering schema then DWARF (e.g. LLDB/GDB/???). 
> > I think it would only require us to change 
> > EmulateInstructionARM64::CreateFunctionEntryUnwind to create an UnwindPlan 
> > with a different register numbering schema and then to lookup the register 
> > based on a different numbering schema using GetRegisterInfo in functions 
> > where we want to reference s0-s31/d0-d31. In theory this should be a simple 
> > change but I won't be surprised if changing the register numbering breaks 
> > something.
> > * Introduce the concept of register pieces. This concept already exists in 
> > the DWARF expressions where you can say that a given part of the register 
> > is saved at a given location. I expect that doing it won't be trivial but 
> > it would solve both this problem and would improve the way we understand 
> > DWARF as well.
> >
> > About your idea about saying that we saved v8&v9 even though we only saved 
> > d8&d9: I think it is a good quick and dirty solution but it has a few 
> > issues what is hard to solve. Most importantly we will lie to the user when 
> > they read out v8&v9 what will contain some garbage data. Regarding 
> > big/little endian we should be able to detect which one the inferior uses 
> > and we can do different thing based on that (decide the location of v8&v9) 
> > but it will make the hack even worth.
> >
> > Tamas
> >
> > On Tue, Oct 11, 2016 at 6:15 PM Jason Molenda <jmole...@apple.com> wrote:
> > Hi Tamas, I'm writing some unit tests for the unwind source generators - 
> > x86 last week, arm64 this week, and I noticed with this prologue:
> >
> >
> >
> > JavaScriptCore`JSC::B3::reduceDoubleToFloat:
> >
> >     0x192b45c0c <+0>:  0x6db923e9   stp    d9, d8, [sp, #-0x70]!
> >
> >     0x192b45c10 <+4>:  0xa9016ffc   stp    x28, x27, [sp, #0x10]
> >
> >     0x192b45c14 <+8>:  0xa90267fa   stp    x26, x25, [sp, #0x20]
> >
> >     0x192b45c18 <+12>: 0xa9035ff8   stp    x24, x23, [sp, #0x30]
> >
> >     0x192b45c1c <+16>: 0xa90457f6   stp    x22, x21, [sp, #0x40]
> >
> >     0x192b45c20 <+20>: 0xa9054ff4   stp    x20, x19, [sp, #0x50]
> >
> >     0x192b45c24 <+24>: 0xa9067bfd   stp    x29, x30, [sp, #0x60]
> >
> >     0x192b45c28 <+28>: 0x910183fd   add    x29, sp, #0x60            ; =0x60
> >
> >     0x192b45c2c <+32>: 0xd10a83ff   sub    sp, sp, #0x2a0            ; 
> > =0x2a0
> >
> >
> >
> >
> >
> >
> >
> > EmulateInstructionARM64::EmulateLDPSTP interprets this as a save of v31.  
> > The use of reg 31 is an easy bug, the arm manual C7.2.284 ("STP (SIMD&FP)") 
> > gives us an "opc" (0b00 == 32-bit registers, 0b01 == 64-bit registers, 0b10 
> > == 128-bit registers), an immediate value, and three registers (Rt2, Rn, 
> > Rt).  In the above example, these work out to Rt2 == 8 (d8), Rn == 31 
> > ("sp"), Rt == 9 (d9).  The unwinder is incorrectly saying v31 right now 
> > because it's using Rn -
> >
> >
> >
> >   if (vector) {
> >
> >     if (!GetRegisterInfo(eRegisterKindDWARF, arm64_dwarf::v0 + n, 
> > reg_info_Rt))
> >
> >       return false;
> >
> >     if (!GetRegisterInfo(eRegisterKindDWARF, arm64_dwarf::v0 + n, 
> > reg_info_Rt2))
> >
> >       return false;
> >
> >   }
> >
> >
> >
> > This would normally take up 32 bytes of stack space and cause big problems, 
> > but because we're writing the same reg twice, I think we luck out and only 
> > take 16 bytes of the stack.
> >
> >
> >
> > We don't have dwarf register numbers for s0..31, d0..31, so we can't track 
> > this instruction's behavior 100% correctly but maybe if we said that
> >
> >
> >
> > That would be an easy fix, like
> >
> >
> >
> >   if (vector) {
> >
> >     if (!GetRegisterInfo(eRegisterKindDWARF, arm64_dwarf::v0 + t, 
> > reg_info_Rt))
> >
> >       return false;
> >
> >     if (!GetRegisterInfo(eRegisterKindDWARF, arm64_dwarf::v0 + t2, 
> > reg_info_Rt2))
> >
> >       return false;
> >
> >   }
> >
> >
> >
> >
> >
> > We don't have dwarf register numbers for s0..31, d0..31, so I don't think 
> > we can correctly track this instruction's actions today.  Maybe we should 
> > put a save of v8 at CFA-112 and a save of v9 at CFA-104.  As long as the 
> > target is operating in little endian mode, when we go to get the contents 
> > of v8/v9 we're only actually USING the lower 64 bits so it'll work out, 
> > right?  I think I have that right.  We'll be reading garbage in the upper 
> > 64 bits - the register reading code won't have any knowledge of the fact 
> > that we only have the lower 32/64 bits available to us.
> >
> >
> >
> >
> >
> > Throwing the problem out there, would like to hear what you think.  I don't 
> > want to encode buggy behavior in a unit test ;) so I'd like it for us to 
> > think about what correct behavior would be, and do that before I write the 
> > test.
> 

_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to