Recent

Author Topic: New debugger for Mac based on lldb (Call for testers)  (Read 21361 times)

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 5114
    • wiki
Re: New debugger for Mac based on lldb (Call for testers)
« Reply #120 on: February 06, 2019, 10:55:36 pm »
Quote
Commenting out the line "pointer(b):= pointer(high(qword));" eliminates the exception.
Yes this line of code intentionally and seriously screws up the string. And it is expected that the test app, does no longer work thereafter.

The point is, the debugger should not crash.

kcandrews

  • New member
  • *
  • Posts: 42
Re: New debugger for Mac based on lldb (Call for testers)
« Reply #121 on: February 08, 2019, 06:17:20 pm »
As info, starting from 2.0.0 Lazarus base with your fixes, today I successfully upgraded to Mojave as a working environment.  Lldb debugger works as it did in High Sierra with fully functional breakpoints, exception "prefix/suffix name-mangling" fixes, and stepping thread-id fixes.  Thanks again for all your work on this!

Steps involved:

1. Performed standard Mojave OSX upgrade from Apple App Store and updated to 10.14.3 Mojave using new System Preferences/Software Update.

2. Upgraded/installed xcode command line tools using terminal command: "xcode-select --install"  Note Xcode is now 10.1 version.

3. Installed FPC 3.04a  to automatically cover needed library path for /usr/lib/crt...
https://forum.lazarus.freepascal.org/index.php/topic,42657.msg300589.html#msg300589

Keith
« Last Edit: February 11, 2019, 11:45:56 pm by kcandrews »

kcandrews

  • New member
  • *
  • Posts: 42
Re: New debugger for Mac based on lldb (Call for testers)
« Reply #122 on: February 10, 2019, 09:53:47 pm »
Martin,
I hadn't really checked out debug "watches" in my multi-threaded app.  Now I have and I discovered that local variables in a function, though they show the correct values when "moused over" (possibly important clue - I will look for where that's done), a watch item existing in the new thread's code, once in the new thread, reveals irrelevant data, apparently from another thread or frame.  Watches displayed under a single threaded app work as expected.  (Also, FWIW, watches work fine in gdb for multi or single-threaded apps).

Also, FWIW, the "arrowed" current thread in the debug/threads window, starts at threadID #1 before I initiate a new thread (proven by breakpoint at start of program).  After a new thread starts up and a breakpoint in that thread #12 successfully stops, the threads window still shows thread ID #1 "selected" (arrow) even though I can also see that the code is breakpointed in threadid #12.  Accordingly the local "str: string" variable which I set in the same thread #12 just before my second breakpoint displays incorrectly.

So, copying your approach with what you did in fixing the step issue, I modified the TLldbInstructionWatchSet.Create in LldbInstructions.pas -- see {kca}:
Code: [Select]
constructor TLldbInstructionWatchSet.Create(AWatch: String;
  AKind: TDBGWatchPointKind
  ; {kca} AThread: Integer = -1; AFrame: Integer = -1);
begin
  case AKind of
  wpkWrite:     inherited Create(Format('watchpoint set variable -w write %s', [AWatch]), {kca}AThread, AFrame);
    wpkRead:      inherited Create(Format('watchpoint set variable -w read %s', [AWatch]),{kca}AThread, AFrame);
    wpkReadWrite: inherited Create(Format('watchpoint set variable -w read_write %s', [AWatch]),{kca}AThread, AFrame);
  end;
end;
And in LldbDebugger.pas, I modified TLLdbBreakpoint.SetBreakPoint adding this under bpkData:
Code: [Select]
    bpkData: begin
      if not Enabled then // do not set, if not enabled
        exit;
      // TODO: scope
      // TODO: apply , Expression, not Enabled
      Instr := TLldbInstructionWatchSet.Create(WatchData, WatchKind,
      {kca} TLldbDebugger(Debugger).FCurrentThreadId, TLldbDebugger(Debugger).FCurrentStackFrame);
      if Expression <> '' then
        FNeededChanges := FNeededChanges + [ciCondition];
    end;

Actually, initially I tried just adding the threadid parameter, but since that didn't work, I added the additional stackframe parameter.  Unfortunately, this didn't solve the problem -- but then I'm pretty much winging it :-)

Any ideas?


« Last Edit: February 10, 2019, 10:03:36 pm by kcandrews »

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 5114
    • wiki
Re: New debugger for Mac based on lldb (Call for testers)
« Reply #123 on: February 10, 2019, 11:02:55 pm »
TLldbInstructionWatchSet is setting a watchpoint. And yes it is broken, but not the issue here. Since a watchpoint is based a watch, it needs thread and frame.

TLldbInstructionExpression is for eval of watches. Well in the NONE FpDebug version. And that is given the thread and frame.

In the LLDB-FpDebug code, it is TLldbDebuggerCommandRegister, and that too is given thread and frame.
It also is TLldbInstructionMemory, but that should not need thread or frame. The memory at a given address is the same for all of them. (Well I have to check if that is true for threadvar)
The address of local vars, is determined by certain register. So if they match the frame, it should be fine.

If you watch the debug output, you will see thread and frame commands issued:
Code: Pascal  [Select]
  1. >> thread select 4
  2. (lldb) thread select 4
  3. >> frame select 3
  4. * thread #4: tid=0x2e38: 0x0042b81b, 0x07A4FEE8, 0x07A4FF00 &&//FULL: \tmp\unit1.pas &&//SHORT: unit1.pas &&//LINE: 93 &&//MOD: project1.exe &&//FUNC: EXECUTE(this=0x048a6ac8) <<&&//FRAME, stop reason = breakpoint 6.1
  5. >> register read --all
They will not always be right before the register command. THe debugger knows what it last did, and if it already is on a thread the command is not needed.



But while debugging this I observed something going wrong.

I get pause at thread 3, frame 0
I switch to thread 1, frame 2
I switch back to thread 3 (which still is at frame 0)

Yet the debugger issues
thread 3
frame 2 

So it did not reset the frame when switching threads.

Please observe if that explains when things go wrong, otherwise observe what the debugger sends.

kcandrews

  • New member
  • *
  • Posts: 42
Re: New debugger for Mac based on lldb (Call for testers)
« Reply #124 on: February 11, 2019, 12:52:39 am »
Martin,
Sorry!  Misunderstood what I was changing -- what I get for "winging it."

Anyway, I somewhat follow you but don't understand the territory very well.

I have attached the debug output from me running my program into the start of the "DoTest" procedure within the new thread.  I looked for through the debug output for "thread select" and "frame select"-- but not sure if I see any issues.  It does seem strange that the debugger goes back to "thread select 1" after "thread select 8" (the new thread).  FWIW, see the attached.  The second attachment is the "Threads window" at the time of the breakpoint stop in my DoTest procedure within the new thread 8.  Do note that the green arrow is on thread one FWIW.

If I look at local variables within DoTest in the "watches" window, they show nonsense values (like the frame or thread is wrong).  However, strangely I can "cursor over" any of these same local variables and see valid values.

Related code where I breakpointed (end of debug output) on the try statement after setting str := 'frogman'.  Again cursor hovering over str in the source code gets me "str = frogman" (strange that should work) while the watch window shows str with a nonsense value:
Code: [Select]
procedure TBacktest.DoTest(SentIndex: integer; SentSingleRun: Boolean);
var
   i, CompleteCount: integer;
   valuelo, valuehi: double;
   str: string;
begin
   str := 'frogman';
try // try finally
try // try except
with TradeSession
do begin             
...

I may need to write a simple threaded program to be more helpful.  My current program uses MTProcs (MultiThreadProcsLaz) which I use to create a pool of threads for efficient parallel financial backtesting over the number of cores my Mac has available.
« Last Edit: February 11, 2019, 04:09:57 am by kcandrews »

kcandrews

  • New member
  • *
  • Posts: 42
Re: New debugger for Mac based on lldb (Call for testers)
« Reply #125 on: February 11, 2019, 06:33:37 pm »
I was able to reproduce a simple illustration of the "watch" problem using the Lazarus/Examples/MultiThreadingExample1 project.

To reproduce, simply build the project as a Cocoa/64bit.  Set a breakpoint at the TMyThreadExecute line 102 "If NewStatus <> fStatusText then begin".  Set a watch for the newStatus string.  Observe that at the breakpoint, you can cursor over a newStatus reference in the source code and see
    ANSISTRING($00000xxxxx)'TMyThreadTime:2019.....'
[Personally I wish it didn't show "ANSISTRING" since that uses a lot of screen real estate when I really just want to see the string, but that's personal.]

Note that in the watch window, newStatus shows a value again showing "ANSISTRING($xxxxxxxxx)ssssssss" where "sssssss" is nonsensical hex characters, etc. picked up from an invalid memory location.

In my case, the new thread is #6 but as before the threads window at the breakpoint has the green arrow at thread #1.  Attached is the IDE Internals/debug output.  I note that only one "thread select" occurs in the debug output -- "thread select 1".

Would appreciate any OSX users confirming this issue too!  Very simple to test...Hopefully you'll see what I see!
« Last Edit: February 11, 2019, 06:59:29 pm by kcandrews »

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 5114
    • wiki
Re: New debugger for Mac based on lldb (Call for testers)
« Reply #126 on: February 11, 2019, 07:35:14 pm »
Personally I wish it didn't show "ANSISTRING" since that uses a lot of screen real estate when I really just want to see the string, but that's personal.
Dry dwarf3 (at least for strings)

Still looking into the rest

kcandrews

  • New member
  • *
  • Posts: 42
Re: New debugger for Mac based on lldb (Call for testers)
« Reply #127 on: February 11, 2019, 07:43:56 pm »
Dwarf3 does stop the "ANSISTRING" output and address info.  Thanks!  (I periodically try to see if I can get gdb to work too -- so accidentally had "dwarf with sets" selected.)  But agree 3 Dry dwarves (dwarfs?) are more pleasant than 3 wet ones :-)
« Last Edit: February 12, 2019, 12:16:31 am by kcandrews »

Hansaplast

  • Hero Member
  • *****
  • Posts: 504
  • Tweaking4All.com
    • Tweaking4All
Re: New debugger for Mac based on lldb (Call for testers)
« Reply #128 on: February 12, 2019, 11:29:48 am »

By request;


I tried Keith's example;


Dwarf2: I do get the same ANSISTRING thing ...
Dwarf3: I get an empty string in the watchlist. However when I hover over the NewStatus variable, it does show me string content without the "ANSISTRING" ...


See attached screenshots.


I'm running Lazarus 2.1.0 r60408M FPC 3.0.4 x86_64-darwin-cocoa (alpha) on Mojave 10.14.3.

kcandrews

  • New member
  • *
  • Posts: 42
Re: New debugger for Mac based on lldb (Call for testers)
« Reply #129 on: February 12, 2019, 05:30:51 pm »
Hans,
Thanks for the confirmation!  There aren't that many of us using OSX and so many configurations are possible...so I don't trust my results as the norm.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 5114
    • wiki
Re: New debugger for Mac based on lldb (Call for testers)
« Reply #130 on: February 12, 2019, 06:22:20 pm »
The "AnsiString" prefix is by design (at least for now)

With dwarf2 the compiler does not tell the debugger that this is a string. The debugger gets the definition
 type AnsiString = ^Char;

And for pointer types, the debugger includes the type name. (this may be made optional in future, but for now it is hardcoded).

In dwarf3 the debugger encodes the string as "array [0..x] of char".
But internally it currently uses different dwarf tokens to encode that type, that it does when encoding an actual array.

So if the debugger detects fpc as compiler, it looks for this internal difference. (If fpc changes that in future, then the debugger will be clueless (again))

So with current fpc, and dwarf 3 the debugger can identify the string type. And then it will not display the type name.

--
This applies to all "FpDebug" based debuggers.

LLDB has no clue of the above.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 5114
    • wiki
Re: New debugger for Mac based on lldb (Call for testers)
« Reply #131 on: February 12, 2019, 08:49:14 pm »
I found one issue that matches your description. (I have not yet tested on Mac, that always takes some extra time)

https://svn.freepascal.org/cgi-bin/viewvc.cgi?view=revision&root=lazarus&revision=60412
Just copy the one line into your install. This is the commit on trunk, so I am not sure if you can take the entire file.

There may be some other issue, that I am still looking into. But if you could test that.

kcandrews

  • New member
  • *
  • Posts: 42
Re: New debugger for Mac based on lldb (Call for testers)
« Reply #132 on: February 12, 2019, 10:22:55 pm »
As per revision 60412, replaced line 2398 in lldbdebugger.pas
Code: [Select]
FInstr := TLldbInstructionExpression.Create(FWatchValue.Expression, FWatchValue.ThreadId, FWatchValue.StackFrame)
and rebuilt the IDE.

As before to test, using the /lazarus/examples/multithreading project, set a single breakpoint at the MyThread.Execute line 102.  Unfortunately, results were as before: hovering over newStatus shows the string value but the "watch" shows newStatus as ''.

FWIW, again note that there is only one "select thread" command in the debug output: "thread select1".  Also the Threads window shows the green arrow on thread ID 1, but thread ID 7 (showing line 102 Function: Execute) implies the watch info should be coming from thread 7.

If this example works on your machine, then it would appear it is OSX related? 

Sorry this is such a "bugger!"  Please let me know if there is anything I can do to help with the debugging.
« Last Edit: February 13, 2019, 12:04:16 am by kcandrews »

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 5114
    • wiki
Re: New debugger for Mac based on lldb (Call for testers)
« Reply #133 on: February 13, 2019, 01:28:51 am »
OK, lets sync yours and my experiences...
Based on the latest changes, including the fix in rev 60413 (One more, over the previous fix)

I have now the MultiThreadingExample1 running on mac 64 bit.

Yes, when it stops, it shows a "useless" value.
The reason appears that the wrong thread is selected. Thread 1 is selected, which is somewhere in the kernel.

Thread 8 should be selected.

If I do select that thread (select in list, then press "current") then all seems fine.

-----------------
I have to look into the correct thread being selected by default.

But please confirm, if this is the same as your issue, or if there are further issues.

kcandrews

  • New member
  • *
  • Posts: 42
Re: New debugger for Mac based on lldb (Call for testers)
« Reply #134 on: February 13, 2019, 05:40:57 pm »
Manually made changes to match rev 60413 but to no effect here :-(

I would be interested to know if the "watch" issue arises in this example (multi-threaded) for your normal working non/Mac environment or if it is specific to OSX, or maybe 64 bit environments?

I confirmed that selecting/pressing current made the "watch" work!   I agree totally that the watch isn't working correctly because the thread isn't set correctly at watch evaluation time.

Personally, I can't get gdb to work under Mojave so I can't test this but it seems if one looked at the GDB debug output for the MultiThreadingExample1, and compared it to the LLDB debug output, it could become apparent where the LLDB version is not matching the commands sent/received to/from the code.  (For me, GDB had no issues in the multi-threaded situation.)

« Last Edit: February 13, 2019, 05:48:01 pm by kcandrews »