[lldb-dev] unit test "functionalities/step-avoids-no debug"
jingham at apple.com
jingham at apple.com
Wed Jul 23 10:58:30 PDT 2014
IME line tables coming from most compilers are flakey and odd, and the debugger just has to suck it up and deal with them as best it can. Sometimes we see cases where the debug info is really wrong (like having line numbers associated with code that clearly doesn't belong to them, or weird incorrect block structure, etc...) in one compiler or the other. If we're facing such a case, then we should not make separate tests for the two compilers, since then we are testing incorrect behavior, but should xfail the test for that compiler and maybe file a bug about the bad debug info. If there's little chance that the compiler will actually be fixed, then we should also put a bug on lldb to work around whatever quirk the line tables are showing (it already has a bunch of these workarounds to deal with odd clang line tables...) It may or may not be able to do that safely. If the latter is true, then the test really should fail for that compiler.
On the other hand there are cases where the code+line tables are confusing but arguably correct in one compiler or the other. In that case, lldb should be able to step reasonably in both cases, and the fact that it doesn't is a bug in lldb. In that case, we should xfail the test and file a bug with lldb.
Another alternative I've had to use when the point of the test is getting somewhere past the problem area and the line tables have been odd - particularly when they are odd in varying ways over time - is to write the test case more carefully: step, look where I landed, then if needed step again. That seems a better way to go than writing separate test cases as well.
I don't think it is a good idea to write separate tests for the two compilers, however. lldb should be able to handle anything that is arguably correct but weird, or weird but predictably weird. Anything beyond that seems either to be covering a bug in the compilers or in lldb or both.
Jim
> On Jul 22, 2014, at 5:30 PM, Doug Snyder <dsnyder at blueshiftinc.com> wrote:
>
>
> the test case “test_step_over_with_dwarf_python” for unit test "functionalities/step-avoids-no debug” passes when compiling the unit test with clang and fails when compiling with gcc, when i run the unit test in linux (ubuntu 14.04). note: to run this test case in linux, you have to comment out the “@skipIfLinux # intermittent failure” line.
>
> the failure happens when the python code in TestStepNoDebug.py does the first self.thread.StepOut() after the breakpoint.
>
> this appears to be caused by gcc generating significantly different code than clang. clang associates 20 bytes of machine code (all of the machine code related to the source line) to the breakpoint source line (line 12), but gcc only associates the first 3 bytes of machine code to line 12. gcc associates the remaining bytes related to line 12 with line 13. the corresponding code for both versions is shown at the bottom of this email.
>
> this difference means that when the self.thread.StepOut() is executed in the clang version, the program steps to the source line of the calling routine (line 19), but the gcc version steps to the next source line (line 13). this mismatch causes TestStepNoDebug.py to report a failure not really caused by lldb, but really just a compiler difference.
>
> it seems like the tests in TestStepNoDebug.py should be rewritten to include different tests for clang and gcc, or the test should be restructured to not rely on compiler differences - at least not clang and gcc differences.
>
>
>
> shown below is the objdump for the clang version. the 20 bytes from 40055c thru 40056f (inclusive) are associated with source line 12 (no bytes are associated with source line 13).
>
> int
> called_from_nodebug_actual(int some_value)
> {
> 400530: 55 push %rbp
> 400531: 48 89 e5 mov %rsp,%rbp
> 400534: 48 83 ec 10 sub $0x10,%rsp
> 400538: 48 b8 d4 06 40 00 00 movabs $0x4006d4,%rax
> 40053f: 00 00 00
> 400542: 89 7d fc mov %edi,-0x4(%rbp)
> int return_value = 0;
> 400545: c7 45 f8 00 00 00 00 movl $0x0,-0x8(%rbp)
> return_value = printf ("Length: %d.\n", some_value);
> 40054c: 8b 75 fc mov -0x4(%rbp),%esi
> 40054f: 48 89 c7 mov %rax,%rdi
> 400552: b0 00 mov $0x0,%al
> 400554: e8 b7 fe ff ff callq 400410 <printf at plt>
> 400559: 89 45 f8 mov %eax,-0x8(%rbp)
> return return_value; // Stop here and step out of me
> 40055c: 8b 45 f8 mov -0x8(%rbp),%eax
> 40055f: 48 83 c4 10 add $0x10,%rsp
> 400563: 5d pop %rbp
> 400564: c3 retq
> 400565: 66 66 2e 0f 1f 84 00 data32 nopw %cs:0x0(%rax,%rax,1)
> 40056c: 00 00 00 00
>
> 0000000000400570 <called_from_nodebug>:
> }
>
>
>
> shown below is the objdump for the gcc version. the 3 bytes from 400556 thru 400558 (inclusive) are associated with source line 12, and the 2 bytes from 400559 thru 40055a (inclusive) are associated with source line 13.
>
> called_from_nodebug_actual(int some_value)
> {
> 40052d: 55 push %rbp
> 40052e: 48 89 e5 mov %rsp,%rbp
> 400531: 48 83 ec 20 sub $0x20,%rsp
> 400535: 89 7d ec mov %edi,-0x14(%rbp)
> int return_value = 0;
> 400538: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
> return_value = printf ("Length: %d.\n", some_value);
> 40053f: 8b 45 ec mov -0x14(%rbp),%eax
> 400542: 89 c6 mov %eax,%esi
> 400544: bf 94 06 40 00 mov $0x400694,%edi
> 400549: b8 00 00 00 00 mov $0x0,%eax
> 40054e: e8 bd fe ff ff callq 400410 <printf at plt>
> 400553: 89 45 fc mov %eax,-0x4(%rbp)
> return return_value; // Stop here and step out of me
> 400556: 8b 45 fc mov -0x4(%rbp),%eax
> }
> 400559: c9 leaveq
> 40055a: c3 retq
>
> 000000000040055b <called_from_nodebug>:
>
>
> doug
>
> _______________________________________________
> lldb-dev mailing list
> lldb-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev
More information about the lldb-dev
mailing list