LLDB Machine Interface Frontend

Hi,

We have an MI (Machine Interface) frontend to LLDB which works out of the box with Eclipse, and likely will work with other GUI's based on the GDB/MI interface. It's been tested on Linux and Windows.

It's ready to upstream and has been developed as an independent tool residing in the LLDB tools folder. It's based on the LLDB public API without any changes to LLDB internals.

The patch is quite large as there are many new files.
How should we go about upstreaming? Should I create a diff review as usual?

Thanks,
Deepak

Hi Deepak,
I can help review/test it when you post the patch.

Thanks,
Abid

Hi Abid,

Thank you, I have attached the zipped patch.
You might have to the change the triple in tools/lldb-mi/MICmnConfig.h for your target.

Please let me know if you have any comments/suggestions.

Thanks,
Deepak

lldb-mi-driver.patch.bz2 (97.4 KB)

First off, thanks for doing this, that is great! If this also works with the gdb-mi mode, you will make our emacs friends happy as well.

If this is just an independent tool that doesn't touch the core lldb sources (and doesn't use anything directly from the gdb MI implementation, since we don't want to mix GPL'ed code in with lldb), I see no reason not to just check it in now, and then iterate on it in situ. That is much easier than handing around patch files, and since there's no chance it will interfere with anybody working on parts of lldb that existed before the patch, can't do any harm. I spoke to GregC and he agrees this is a reasonable course.

Again, thanks for working on this.

Jim

Thanks Jim, have just committed it. Yeah, it works with the GDB/MI interface.

There's no GPL code, it's all written from scratch.
Not all MI commands have been implemented yet, however it should be enough to set breakpoints, view locals.
We're working on adding more commands for viewing/modifying registers, memory etc.

It'll be great if more people from the community can use and test it with other GUIs!

Thanks,
Deepak

Thanks Jim, have just committed it. Yeah, it works with the GDB/MI
interface.

There's no GPL code, it's all written from scratch.
Not all MI commands have been implemented yet, however it should be enough
to set breakpoints, view locals.
We're working on adding more commands for viewing/modifying registers,
memory etc.

It'll be great if more people from the community can use and test it with
other GUIs!

Thanks,
Deepak

​Hi Deepak,

Is this committed to lldb source tree? If yes, then I can update my local
tree and try it with my IDE which also uses GDB/MI
I will report my findings here

Thanks!

Hi Eran,

Yeah, I have committed it to the lldb source tree.
That’s great! Please try it out. Thanks, Deepak

Excellent! Again, thanks for working on this.

Jim

Hi Deepak,

I have just updated and rebuilt the tree on Windows

Starting lldb-mi.exe → instantly crashes

for comparison, starting lldb.exe it starts normally without any crash

I built it using VS2013, I selected the ‘MinSizeRel’ build configuration

Unfortunately, running it under VS, gives a useless backtrace (only addresses)

I could try and build it with debug info, but it just takes too much time :smiley:

Eran

Hi Eran,

I tried it here with a Debug build and a MinSizeRel build, but no crashes.

Did you try to launch it from an IDE or simply ran it?
Could you please try a debug build?

We’ll look into it more to see if we can find something.

Thanks,
Deepak

Hi Eran,

I tried it here with a Debug build and a MinSizeRel build, but no crashes.

Did you try to launch it from an IDE or simply ran it?

​I tried it from the command line

FYI:
I am using Windows 7 (64), Visual Studio 2013 (express edition)
Can you upload your lldb-mi.exe / liblldb.dll somewhere so I could try it
here and see if its a problem with my build?

Could you please try a debug build?

​Will do

Hi Eran,

I tried it here with a Debug build and a MinSizeRel build, but no crashes.

Did you try to launch it from an IDE or simply ran it?

​I tried it from the command line

FYI:
I am using Windows 7 (64), Visual Studio 2013 (express edition)
Can you upload your lldb-mi.exe / liblldb.dll somewhere so I could try it
here and see if its a problem with my build?

Could you please try a debug build?

​Will do

here is the backtrace from the crash (it crashes on a va_copy() call...

arg) :

     msvcr120d.dll!5ccefb53() Unknown
     [Frames below may be incorrect and/or missing, no symbols loaded for
msvcr120d.dll]
     [External Code]

   lldb-mi.exe!CMIUtilString::FormatPriv(const CMIUtilString & vrFormat,

char * vArgs) Line 114 C++
     lldb-mi.exe!CMIUtilString::Format(const CMIUtilString & vrFormating,
...) Line 139 C++
     lldb-mi.exe!CMIDriverMgr::GetAppVersion() Line 577 C++
     lldb-mi.exe!CMICmnLog::Initialize() Line 83 C++
     lldb-mi.exe!MI::ModuleInit<CMICmnLog>(const int vErrorResrcId, bool &
vwrbOk, CMIUtilString & vwrErrMsg) Line 50 C++
     lldb-mi.exe!CMIDriverMgr::Initialize() Line 82 C++
     lldb-mi.exe!DriverSystemInit() Line 199 C++
     lldb-mi.exe!main(int argc, const char * * argv) Line 317 C++
     [External Code]

And for your convenience, here is the "Locals" view during the crash:
vrFormat "%s\n%s\n%s" const CMIUtilString &
vArgs 0x00bdf334 "ÌÌÌÌ| \x15" char *
argsCpy 0x00bdf334 "ÌÌÌÌ| \x15" char *
nFinal 0 int
pFormatted unique_ptr 37 '%' std::unique_ptr<char
[0],std::default_delete<char [0]> >
n 16 int
strResult "" CMIUtilString

Hope it will give you a hint

Hi Deepak,

First, thanks for doing this. I had a quick review. Some comments and questions below.

  1. I tried it on Linux but could not make it work with CDT. I asked CDT to use the MI driver instead of GDB(in Debug Configuration->Debugger tab) but it failed. I was wondering if there are any steps I need to follow before I can run it with eclipse. Any version dependency etc. Also when I run it from command line, it does not seem to handle any mi command that I tried.

-file-exec-and-symbols /home/abidh/demos/act

0^error,msg=“Driver. Received command ‘-file-exec-and-symbols /home/abidh/demos/act’. It was not handled”

-break-insert main

0^error,msg=“Driver. Received command ‘-break-insert main’. It was not handled”

  1. The Code has many comments that are copies in many headers. They will get stale with time. So it is better to have them in one place only so that it is easy to update them. Some example are

"// To implement new MI commands derive a new command class from the command base

// class. To enable the new command for interpretation add the new command class

// to the command factory."

  1. Similar comments about the environment mentioned in many files. Those comments will get stale with time so should be removed.

  2. Not very important, but it would be nice if the comments in the header files before classes and functions are written in the same way as rest of the lldb for consistency sake. I am not sure about the policy but the I don’t see date and author name in rest of the lldb either.

  3. You have added some utility classes for lldb-mi. Some of the functionality may already be available in LLDB. I can understand that you may not want to depend on LLDB internal classes. But there needs to be a way to share code instead of duplicate. May be a shared utility folder where store such files and they can be used by LLDB core and drivers.

  4. Similarly duplication of Driver.cpp would be a maintenance burden. Something we need to think about.

  5. I see some functionality is left as TODOs for Linux and OSX. It would be nice if you could list them somewhere so that people working on those system can try to fill the holes.

  6. In future, we may like to make the generation of log file an option.

Thanks,

Abid

Hi Eran,

Here’s the link to download the MinSizeRel build.
Thanks, Deepak

Thanks for your build Deepak, it starts without any crashes.
However, the implementation is lacking, and I suspect that making it work with any existing IDE that uses GDB/MI will take a lot of effort.

Few comments:

On Windows, I use some extra normal commands that have no counter part in the MI, such as “set new-console on” (which creates a new CMD.EXE and redirects all the application’s std[in|err|out]), ofc, this does not work

The replies from lldb-mi, are a bit different from gdb, for example, consider this interaction between codelite (the IDE) and lldb-mi:

Using gdbinit file: C:\Users\PC\AppData\Local\Temp\codelite_gdbinit.txt
Current working dir: D:\src\TestArea\wxCrafterTester
Launching gdb from : ./Debug
Starting debugger : C:\Users\PC\Desktop\MinSizeRel\lldb-mi.exe --command=“C:\Users\PC\AppData\Local\Temp\codelite_gdbinit.txt” --interpreter=mi “./wxCrafterTester”

00000001-break-insert -f -t main
00000002-enable-pretty-printing
Debug session started successfully!

00000003-exec-arguments
00000004-exec-run
lldb-mi>>1^error,msg=“Command ‘break-insert’. Breakpoint ‘main’ invalid”
1^error,msg=“Command ‘break-insert’. Breakpoint ‘main’ invalid”

Command: 00000001: -break-insert

According to the docs, it can accept function name (its sole purpose here is to place a temporary breakpoint at ‘main’ (hence, the “-t”) ). It seems like lldb-mi does not expect a function name but rather a location? (did not try that)

Also, the reply from lldb-mi is different:

codelite prepends a transaction ID (8 digits number with fixed length) for each command it sends over to gdb, it is expecting gdb/lldb-mi to reply with these exact 8 digits (including all padding zeros)

this is not the case here (lldb-mi replied with ‘1’ instead of ‘00000001’)

After changing codelite’s gdb settings (i.e. disabled the option to temporarily break at main) I hit another obstacle: I can not place a breakpoint:

00000005-break-insert -f "“D:/src/TestArea/wxCrafterTester/MainFrame.cpp:15"”

and lldb-mi replied with:

lldb-mi>>MI: Error: Command Args. Validation failed. Not all arguments or options were recognized: "“D:/src/TestArea/wxCrafterTester/MainFrame.cpp:15"”
MI: Error: Command Args. Validation failed. Not all arguments or options were recognized: "“D:/src/TestArea/wxCrafterTester/MainFrame.cpp:15"”
lldb-mi>>5^error,msg="Command ‘break-insert’. Command Args. Validation failed. Not all arguments or options were recognized: ““D:/src/TestArea/wxCrafterTester/MainFrame.cpp:15"””
5^error,msg="Command ‘break-insert’. Command Args. Validation failed. Not all arguments or options were recognized: ““D:/src/TestArea/wxCrafterTester/MainFrame.cpp:15"””

At first I thought its because of the volume (“D:”) part of the file name, so I changed the settings to send file name without full path, same error occured …

Also, it seems that when lldb-mi hits the first error it simply hangs ( I don’t see my application being launched )

Some more observations:

Commands that are not supported (and used by codelite IDE):

// -exec-arguments

00000010-exec-arguments 1
lldb-mi>>11^error,msg=“Driver. Received command ‘00000011-exec-arguments’. It was not handled. Command ‘exec-arguments’ not in Command Factory”

// -enable-pretty-printing

00000010-enable-pretty-printing
lldb-mi>>10^done,supported=“0”

This was all tested on Windows 7, 64bit.

Trying to debug an executable built with g+±4.8.1 32bit, (MinGW, no MSYS)

Thanks for you work,
Eran

Hey Eran,

Comments inline.

The implementation is certainly lacking, we stated that it’s the initial commit and it’s only tested with Eclipse. With Eclipse it works correctly. I should add at the moment only remote targets are supported. The amount of effort to get an existing GDB/MI interface up and running however is now drastically lower than previous! Yeah, for those sorts of commands best bet is you add that yourself. Eclipse certainly doesn’t use it, and that’s our initial target. -t and breakpoints on functions are certainly supported at this stage, the code is all there and we use it. Will have to look at this one. Ack. The standard I guess does say any arrangement of digits, we’ll get this one fixed :slight_smile: We’ll see if we can repo this sort of thing and have a look at it. We use it on windows too so the volume being part of the file name shouldn’t really matter. Yup, lots of commands still to write. At the moment though you can certainly use this frontend and it’s usable on Eclipse, for remote targets anyway. Breakpoints, single stepping, local variables, stack traces are all there and supported. Obviously there will be issues given we’re only testing on Eclipse. As every ‘standard’ implementer knows, the only standard thing about all the implementations is that they are guaranteed to all be used in subtly different ways :slight_smile: Thanks for taking the time to check it out, this feedback is incredibly valuable. At the end of the day, we want to make sure the frontend will work with as many different IDEs as possible. Cheers, Colin

I found a little problem that was causing lldb-mi to reject every command that I tried from the command line.

mi-command ==>

[ token ] “-” operation ( " " option )* [ " --" ] ( " " parameter )* nl

Current implementation is expecting token in every command while this seems to be optional in the standard.

Still to figure why my eclipse times out when I try to connect with lldb-mi.

Regards,

Abid

Hi Abid,

Eclipse always sends a number as the token which is used to the identify the commands.
You're right, the spec says it's optional.

From our investigation, the reason for Eclipse timing out could be that it expects a "(gdb)" as the first string.
Could you simply add an "std::cout<<"(gdb)"<<std::endl;" at the beginning of lldb-mi, just to see if that fixes the problem?
We're working on a proper solution for this.

Thanks,
Deepak

Thanks Deepak. That solved the timeout issue. I have seen some other issues that are mostly related to missing commands but those can be sorted with time.

Thanks,

Abid