[lldb-dev] 32-bit linux IsWatchpointHit assertion failure due to WriteRegister

Todd Fiala tfiala at google.com
Mon Mar 3 08:47:26 PST 2014

Hi Matthew,

Thanks for the analysis.

> #define DR_OFFSET(reg_index) \
>    (0xFC + (reg_index * 4))
> Can't we just use this in our lldb code?

We could, but the fact that it is not lining up right on your side means
all the parts between the misaligned bits and the DR registers are also
broken.  So there's something deeper here going on.

> As the fpregs and fpxregs structs are of differing sizes pushes the
offsets of the dr registers out.

I think you're referring to this part, right?

+    {
+        struct
+        {
+            uint64_t fip;   // Instruction Pointer
+            uint64_t fdp;   // Data Pointer
+        } x86_64;
+        struct
+        {
+            uint32_t fioff;   // FPU IP Offset (fip)
+            uint32_t fiseg;   // FPU IP Selector (fcs)
+            uint32_t fooff;   // FPU Operand Pointer Offset (foo)
+            uint32_t foseg;   // FPU Operand Pointer Selector (fos)
+        } i386;
+    } ptr;

Both the x86_64 and i386 portion of the structure are unioned, and both are
128 bits wide.

+    MMSReg   stmm[8];       // 8*16 bytes for each FP-reg = 128 bytes
+    XMMReg   xmm[8];        // 8*16 bytes for each XMM-reg = 128 bytes
+    uint32_t padding[56];

These are different than the true x86_64 version to match the x86 32-bit

The reason I changed them was to solve the original issue of the 32-bit
lldb running against a 32-bit inferior trying to read the 64-bit register.
 Your patch had added some code to say "when reading a 64-bit register
value, really just return 32-bits".  But the reason it was trying to read
64-bits was because of the way the FPR_SIZE macro was defined.  I added a
mechanism to allow it to be possibly defined ahead of time, which is what
we now do in the case of the i386 register infos setup within the Linux
RegisterContext i386 class here:

+#define FPR_SIZE(reg) sizeof(((FPR_i386*)NULL)->reg)

That, in turn, required that the proper elements be defined in the floating
point save region.

Today I'm going to try a few things:

* build the 32-bit setup with configure/make.  This might expose different
behavior on my 32-bit systems vs. the cmake/ninja builds I did last week.

* add some logging during 32-bit register setup to dump the offsets of all
the relevant parts.  I'm going to spit out what I'm getting on my end and
would like you to do the same so we can see where we're getting different
alignment.  This might end up boiling down to compiler flags (which might
be exposed when I use configure/make, and might imply we need some
#pragma/alignment decls).

It would be great if you can confirm a few things just to make sure all my
assumptions are right:
* What OS are you using?  ('uname -a' data)
* What compiler are you using? (compiler version string)
* What hardware is this running on?

Thanks Matthew!  We'll get this all straightened out.

On Mon, Mar 3, 2014 at 6:02 AM, Matthew Gardiner <mg11 at csr.com> wrote:

> Yes, my latest pain in 32-bit linux occurs due to the offset calculations
> for dr6/7 being broken by the inclusion of the extended floating point
> registers structure in "struct UserArea". I'm not really sure what we are
> trying to model here, since, looking at sys/user.h, it's the regular FP
> registers (user_fpregs_struct) which comprise the user area not the
> extended ones (user_fpxregs_struct).
> I did try to fix this issue by reinstating the previous definition for
> FPR_i386, i.e.
> struct FPR_i386
> {
>     int32_t cwd;
>     int32_t swd;
>     int32_t twd;
>     int32_t fip;
>     int32_t fcs;
>     int32_t foo;
>     int32_t fos;
>     int32_t st_space [20];
> };
> Unfortunately, this results in a world of pain, since the numerous
> "DEFINE_FPR" invocations in RegisterInfos_i386.h rely on the elements
> contained in user_fpxregs_struct.
> So, I solved this issue in a different (and in my opinion simpler) way -
> by using the following macro to calculate the offset of a debug register in
> the user:
> #define DR_OFFSET(reg_index) \
>     (0xFC + (reg_index * 4))
> Can't we just use this in our lldb code?
> Why do we currently calculate the offsets with copied structures? Do we
> actually use the structures as structures as well? This is a source of bugs.
> So I'll repeat what I hint to above...
> Can we remove the copied user/register structures and replace the required
> offsets with integral constant definitions please?
> thanks
> Matthew Gardiner
> Member of the CSR plc group of companies. CSR plc registered in England
> and Wales, registered number 4187346, registered office Churchill House,
> Cambridge Business Park, Cowley Road, Cambridge, CB4 0WZ, United Kingdom
> More information can be found at www.csr.com. Keep up to date with CSR on
> our technical blog, www.csr.com/blog, CSR people blog, www.csr.com/people,
> YouTube, www.youtube.com/user/CSRplc, Facebook,
> www.facebook.com/pages/CSR/191038434253534, or follow us on Twitter at
> www.twitter.com/CSR_plc.
> New for 2014, you can now access the wide range of products powered by
> aptX at www.aptx.com.
> _______________________________________________
> lldb-dev mailing list
> lldb-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev

Todd Fiala | Software Engineer | tfiala at google.com | 650-943-3180
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20140303/8e83ceb1/attachment.html>

More information about the lldb-dev mailing list