This is an archive of the discontinued LLVM Phabricator instance.

[lldb] [test/Register] Add read/write tests for x87 regs
ClosedPublic

Authored by mgorny on Sep 30 2020, 8:47 AM.

Details

Summary

Add a partial read/write tests for x87 FPU registers. This includes
reading and writing ST registers, control registers and floating-point
exception data registers (fop, fip, fdp).

The tests assume the current (roughly incorrect) behavior of reporting
the 'abridged' 8-bit ftag state as 16-bit ftag. They also assume Linux
plugin behavior of reporting fip/fdp split into halves as (fiseg, fioff)
and (foseg, fooff).

Diff Detail

Event Timeline

mgorny created this revision.Sep 30 2020, 8:47 AM
Herald added a project: Restricted Project. · View Herald TranscriptSep 30 2020, 8:47 AM
mgorny requested review of this revision.Sep 30 2020, 8:47 AM
labath accepted this revision.Oct 1 2020, 12:26 AM

This is great. Thanks.

lldb/test/Shell/Register/x86-fp-read.test
8

Maybe add a # CHECK: Process {{.*}} stopped line here. That will restrict the following CHECK-DAGs to match after it, which will make FileCheck output more useful. Without it, FileCheck's "Searching from here" snippet will start at the very beginning of the lldb output, which will not be very helpful.

This revision is now accepted and ready to land.Oct 1 2020, 12:26 AM
mgorny marked an inline comment as done.Oct 1 2020, 2:29 AM
mgorny updated this revision to Diff 295500.EditedOct 1 2020, 2:33 AM
mgorny retitled this revision from [lldb] [test/Register] Add partial read/write tests for x87 regs to [lldb] [test/Register] Add read/write tests for x87 regs.
mgorny edited the summary of this revision. (Show Details)

Done as requested + improved the tests:

  • switched to FDIV on memory operand, to be able to test FDP
  • added disassembly-based test for FIP and print-based test for FDP (assuming Linux behavior for fiseg/fioff/foseg/fooff, this certainly breaks NetBSD and might break some more platforms)
  • figured out how to make write test work while restoring exception state
  • added FXSAVE-based check whether writing other registers works (this also includes potential future support for MXCSR)
mgorny added a comment.Oct 1 2020, 2:35 AM

I'd use some help improving the assembly, as explained below.

lldb/test/Shell/Register/Inputs/x86-fp-write.cpp
24

Now, here's the problem. This works just fine when built with clang but segfaults when built with gcc (apparently tries to access 0x0).

mgorny added inline comments.Oct 1 2020, 4:40 AM
lldb/test/Shell/Register/Inputs/x86-fp-write.cpp
24

Turned out to be an alignment issue. Will update the patch shortly.

labath added inline comments.Oct 1 2020, 5:03 AM
lldb/test/Shell/Register/x86-fp-read.test
28–29

zero is pretty common value. It would be better to check that the address actually points to the address of the zero variable. I think something like this ought to do it:

print &zero
# CHECK: (uint32_t *) $0 = [[ZERO:0x[0-9a-f]*]]
print (uint32_t*)($foseg * 0x100000000 + $fooff)
# CHECK: (uint32_t *) $1 = [[ZERO]]

Something similar can be done with the disassemble command too. That way we'll see the actual register value in case it turns out to be wrong.

mgorny updated this revision to Diff 295534.Oct 1 2020, 5:15 AM

Fixed segfault when built with GCC and fixed my poor attempt to run FXSAVE with REX.W prefix. Now it correctly gets 64-bit FIP and FDP, though it's unclear whether the apparent truncation is a bug in LLDB writing it or some other kind of limitation.

labath added a comment.Oct 1 2020, 5:32 AM

Fixed segfault when built with GCC and fixed my poor attempt to run FXSAVE with REX.W prefix. Now it correctly gets 64-bit FIP and FDP, though it's unclear whether the apparent truncation is a bug in LLDB writing it or some other kind of limitation.

I think that could be an architectural cpu limitation. IIUC, even though the addresses are nominally 64-bit, not all addresses within that space are actually usable -- only the topmost and bottommost XX GB (TB) of the address space are. It could be that the cpu does not actually store all of the bits of these registers, but rather just sign-extends the most significant usable bit.

mgorny added inline comments.Oct 1 2020, 5:32 AM
lldb/test/Shell/Register/x86-fp-read.test
28–29

Cool idea, thanks!

As for FIP, I suppose that would require getting address corresponding to the FDIV instruction somehow. I suppose we can rely on constant-length encoding on int3 and fdivs ..., so I guess $rip-3 might work.

labath added inline comments.Oct 1 2020, 5:35 AM
lldb/test/Shell/Register/x86-fp-read.test
28–29

I was thinking you could disassemble the main function and capture the address before the fdivs instruction. But yes, a fixed offset from $rip should work just fine...

mgorny updated this revision to Diff 295539.Oct 1 2020, 5:39 AM

Update fp-read tests to verify FIP/FDP addresses, as suggested by Pavel.

labath accepted this revision.Oct 1 2020, 5:43 AM

cool

mgorny updated this revision to Diff 295552.Oct 1 2020, 6:31 AM

Use safer values for fiseg and foseg, to avoid truncation.

mgorny added a subscriber: teemperor.

@teemperor would you perhaps be interested in testing this on macos before I commit it?

mgorny updated this revision to Diff 295980.Oct 3 2020, 8:43 AM

Added missing -g to x86-fp-read.cpp build, as necessary to get address of zero.

This revision was automatically updated to reflect the committed changes.

This is failing on GreenDragon so I've XFAILed the tests (temporarily). Can you take a look and see if they can be fixed and re-enabled?

commit 0f08a1a5b162dcd2caf1b76827b917ca69e3e48d (HEAD -> master, origin/master, origin/HEAD)
Author: Jonas Devlieghere <jonas@devlieghere.com>
Date:   Sat Oct 3 22:36:28 2020 -0700

    [lldb] [test/Register] Mark new FP reg tests XFAIL on Darwin

    This is failing on GreenDragon:
    http://green.lab.llvm.org/green/view/LLDB/job/lldb-cmake/24066/

This is failing on GreenDragon so I've XFAILed the tests (temporarily). Can you take a look and see if they can be fixed and re-enabled?

I'm afraid I don't have enough context. Would you be able to rerun them for me with FILECHECK_DUMP_INPUT_ON_FAILURE=1 envvar? Also, I'd suggest adding this to buildbot — it's really helpful if something starts failing.

This is failing on GreenDragon so I've XFAILed the tests (temporarily). Can you take a look and see if they can be fixed and re-enabled?

I'm afraid I don't have enough context. Would you be able to rerun them for me with FILECHECK_DUMP_INPUT_ON_FAILURE=1 envvar? Also, I'd suggest adding this to buildbot — it's really helpful if something starts failing.

I think it recently became the default? Either way the bot has the input:

http://green.lab.llvm.org/green/view/LLDB/job/lldb-cmake/24066/testReport/junit/lldb-shell/Register/x86_64_fp_write_test/
http://green.lab.llvm.org/green/view/LLDB/job/lldb-cmake/24066/testReport/junit/lldb-shell/Register/x86_fp_read_test/

Well, it's not full input but sure, it's good enough. So I suppose the problem is that the register is named stmm instead of st. I suppose we can use a regex to fix read test, and maybe teach lldb stX alias for write test.