 I'm going to talk to you about LLDB in free BSD, but in order to get there, I'm going to talk a little bit about the history so that you'll understand how we got to where we are and how that relates to where we hope to go in the future. So first of all, why do we need a new debugger? As you know, the characteristic of BSDs is the concept of a base system, cohesive set of operating system components that are developed and released and bugged and built together and released as an integrated whole. So one of the components of the base system is the tool chain, which includes the compiler and the linker and all those things, and of course a debugger. Free BSD has a long history with GDB in the base system, the GNU debugger. So the history actually goes a little bit further off to the left of this chart. I mined the contrib slash GDB directory to find out exactly when GDB releases came in over time. And the very first free BSD release actually predates the way that the source tree is used now. So I booted up a free BSD 1.0 ISO image in a VM to see. And free BSD 1.0 in 1993 had GDB 3.5 in it, and then in 96 we imported the source for 4.16 into free BSD. So the light blue bar on the top represents upstream releases, just selected ones. And then maybe that's future light purple bar down below represents the time at which we imported that release into free BSD. So over time, new minor releases would come out and they'd get imported. So we skipped a little while, and then 4.18 came out, we imported it. A new major version came out 5.0, and we imported it. And each time this would happen, we'd have a bit of work to do to adapt the new release to run properly on free BSD. So the sorts of things that had to be done are support for free BSD's threading model, support for kernel debugging, all of that didn't exist in the upstream GDB project. And then as time went on, additional GDB releases came out and we imported them basically once every year, once every other year sort of thing, a GDB release would get imported into free BSD. And over this time, the patch set for supporting GDB on free BSD kept growing and growing and was a larger amount of work on each new import. And all of this history predates my direct involvement with debuggers on free BSD. So I don't have a direct reference, but I talked to the people who were doing the work at the time and asked for a little bit of the history. And basically the developers who were working on GDB on free BSD at the time tried to work with upstream GDB to get the patches pushed upstream, because of course it's a lot less effort if the changes for your own OS are integrated directly in the upstream project. If you have to, every time a new upstream comes out, do a whole bunch of work to bring it into your use case, then it just becomes a larger and larger and larger maintenance overhead. And so they tried to work with upstream GDB and get the patches pushed upstream, but were completely unsuccessful. Basically it was expectations on the GDB side that either they couldn't meet or couldn't keep up with the pace of ongoing upstream changes. I'm not sure of the exact details, but this is a common theme I've heard that it's often very difficult to work with the GDB and GCC upstreams. At least from the free BSD community. And of course GCC is the same sort of thing we've imported lots and lots of versions. It's a bit more frequent and a few sort of more odd things where we've either waited a long time or some of them actually even go backwards because we imported a snapshot and then updated to the eventual final release. And if we extend the history out to today, I've skipped quite a few releases. I put GDB 7.0 to show a new major release came out just before 2010. And GDB 7.8 is the most recent, I think it was just this last July. So of course GDB development is still ongoing. And we've stopped as of 6.1.1 in 2004. So in the base system in free BSD today, we have a 10 year old version of GDB. And it's really showing its age. So C++ debugging is really lacking in our base GDB. And threaded inferior target support is also not particularly good right now. And basically what ended up happening at this point was the developers who were doing this work kept, I guess, got tired of the effort of always trying to bring in the new versions and basically just gave up. Given lacking sufficiently important bug fix or new feature in those next few releases there was no real desire to put in the effort to do the import. And then you'll notice that GCC also stopped and that's when the GNU project switched to GPLv3. And so GPLv3 has a number of new restrictions and new clauses that some major free BSD committers and free BSD consumers and contributors to free BSD sort of outside of the committer base found onerous or objectionable. And so the free BSD project, the current stance is that we won't take a update from a GPLv2 component in the base system to GPLv3 without very careful consideration by the core team to determine if that's the way we want to go or if there's something else we'd want to do. So with the compiler side, we've switched to Clang and LLVM. 10.0 has Clang as the system compiler for the main tier one architectures. And that's working out quite well for us in the base system as far as the compiler goes, I'm very happy with it. It compiles almost a very large portion of the port's tree and works quite well. So that's been a very successful transition. And then over time, the additional other architectures like MIPS will transition to Clang as a system compiler as well. So it was clear that we needed a new debugger. We had no path forward and we had no way to move forward. And the GDB that we had was increasingly showing its age and becoming a problem. So at the time, there were a few debugger projects out there, open source or otherwise, and a few new projects started springing up within the FreeBSD community and in the broader open source community. But none of them really gained critical mass and became a viable option for the FreeBSD base system. And then in 2010 at Apple's Worldwide Developer Conference, WWDC, they announced that they had been working on a debugger project called LLDB. And it's built on top of Clang and LLVM as foundational libraries. And it basically follows the same model as Clang and LLVM as far as in the same family, it's now in the same repository and used the same bug tracker. It's a member of the Clang and LLVM family. So just looking briefly at LLDB's history, the chart just represents lines of code data from Black Duck Open Hub, which used to be called OLO. And from mid 2010 to about mid 2012, it was really an Apple project. I looked through the commit history in the repository at email address, domain names, and basically speaking, Apple did pretty much all of the work during this time. I did look to see who the most prolific non-apple.com committer was. And so I looked and it turns out they were responsible for just under 2% of the number of commits during this time period. And so I wanted to see a little bit more about what they were working on and what the relationship was. And it turns out they were actually an intern at Apple during this time. And their email address switched to apple.com later on in the history. So I looked at the next most prolific committer and they were responsible for about 1.5% of the commits, but notably including some initial Linux support. So during this time a few patches landed for Linux support and for a very initial port to FreeBSD. So FreeBSD developers Mark Peek and Kip Macy did a lot of the early work. And there was someone else even before that that went in during this time. So the Linux support existed in LLDB. And then Kip Macy and Mark Peek took that, refactored that support into a set of POSIX classes and then had FreeBSD classes and Linux classes that derived from the POSIX base class. And then starting in mid-2012, Intel's open source group in Waterloo, Ontario, Canada, just down the street from where I live, started working on this. They had about, I think they had four committers, fairly consistently developing LLDB and their primary focus was on Linux. So they wanted it to be a very capable debugger on Linux. And there were a few other people at Intel that were committing at the same time, but primarily a small group was doing quite a lot of work. And then in early 2013, I started working. And that little bump there is just an anomaly of the data from BlackDuck. It's not that I was a very prolific committer just doing all kinds of work. What really happened there is one of the Intel guys committed a whole bunch of API documentation and Open Hub counted that as lines of code. So it looks like I showed up and did a ton of work, but really it's just a little glitch. So my interest in LLDB came from a few different areas. But one of the motivating factors is the work I'm doing with the computer lab at the University of Cambridge, as mentioned, in collaboration with SRI in the US on a DARPA sponsored project for hardware compartmentalization at the instruction set level. So this introduces a whole bunch of interesting new requirements as far as registers and memory attributes and things that need to be just shown in a debugger context. So that's one of the reasons that I started getting involved in LLDB. But in order to be able to explore some of those new avenues, I first had to go and do a lot of work just to get LLDB on free BSD into a good state. So when I started, the port had bit rotten a little bit. It didn't even build actually on free BSD. And so I had to first fix the build issues and then it did what you would start it. And it just basically didn't actually work. So solving a few of those issues, finally I got to the point of it's usable as a basic debugger. You can start up bin LS, set a break point at main, and it actually does something. And then I worked on the test suite, so it was the same sort of thing. At first, the test suite didn't run on free BSD and I had to do a whole bunch of things to get it to pick the right compiler and the right libc++ and those sorts of things and it's not a lot of difficult work. It's just tedious to iterate through all of those special cases where they've got if platform dot starts with Linux and et cetera, et cetera, and then just adding a free BSD case on the end. But there were a lot of those sorts of little things that needed to get cleaned up. And in the beginning of this year, Google has come on board to start doing a lot of LLDB work as well, which is really important because the Intel guys, that group has actually shut down now. The office down the street for me has closed and they're not working on this anymore. And there's a lot of work to do here in sort of the base infrastructure beyond just porting to Linux or porting to free BSD as well. So it's excellent that another company with significant resources has taken a large interest in LLDB and their primary platforms of interest are Linux, Android, and they're doing some work on Windows as well. And then looking through the, I looked through the rest of the commit history to see who else has been involved and I just put some of the logos based on domain names that I found in there. And there are quite a few people who are doing one or two patches here and there or build fixes and things. So my point here is really just that LLDB is very much transitioning from what was originally an Apple project to what is now very much a community supported and very credible and viable debugger. So I'm going to talk a little bit about LLDB's design. And so LLDB in a similar way to Clang and LLVM is built as a modular set of components that can be reused for other purposes. So LLDB actually is built as a library that other projects can link against and use its functionality. So it's designed to vend an API and if you're writing a command line debugger. So you type LLDB at the command line and you're using it through a UI or through a text interface. It's actually just linking against libLDB the same way that if you're using a text code on OS 10, it's linking against the same kind of LLDB library underneath. And you'll see Python actually on here in two different spots. So Python's on the top as a consumer of the LLDB API and then it's down here as a script interpreter. So for the top case, you can write a Python script that says import LLDB and you basically get an LLDB object that you can then have start up a process to debug set break point single step through it. So you could write an entire debugger front end in Python, for instance, just using the library under the hood without actually having to run a LLDB binary that you communicate with through some sort of interface. And then the Python down here in the scripting interpreter is something that we don't have at all in the base system today in GDP. The scripting interface there is quite limited in what old versions of GDP can do. Newer GDP, contemporary GDP, has a Python scripting interface as well. But it allows you to do things like if you need to walk a linked list that's in your target process, for instance, you can write a script in Python that will read member variables and do whatever you want to do so that you can automate the sorts of tasks that you need to execute like that. You can also use the script interpreter built into LLDB to add new commands, new functionality. So for instance, there's a memory search command that someone added at some point and that's actually implemented in Python. The expression parser up here is one really interesting part of the way LLDB works. So as you can see, I mentioned that the orange parts there are components that build heavily on Clang or LLVM, built on top of Clang or LLVM foundation parts. So the disassembler in the plug-in side is one part. LLVM provides the disassembly capability. But the expression parser is really neat. So one of the challenges of a debugger is giving a faithful expression parser. So you can type in something at the command line to examine some complex object and examine member variables in some really complex variable you have in the function that you're stopped in in the debugger. And what LLDB does is takes the expression that you've entered at the command line, wraps it in a function, in a function sort of wrapper and a template, and not a C++ template, just a boilerplate around your expression. And then passes it off to Clang to parse it so that any expression, any code that you could enter in your original source that you've compiled and are now debugging can also be entered at the command line. And have LLDB through Clang execute that. And so what LLDB does is takes the Clang AST, does a few transformations at that level, converts it to LLVM IR, does a few more transformations at that level. And then depending on what sorts of operations your expression actually performs, it either has an IR interpreter that can figure out if you're just reading a simple variable, it'll just do that without doing anything particularly complex. And if you have a more complicated expression that it can't interpret, it will jit it and execute it in your targets in the context of your target. So that you can do sort of any function call you want with there's certain limitations, but generally speaking you can execute any sort of function call you want. You can define local variables in your expression in your expression context that will remain from one expression to the next. And I'll show a very brief demo of that later on. The data form runners are one other item I'll talk about just briefly. So this is built into LLDB and it knows how to interpret the libstandard C++ or lib C++, any of the sort of standard classes. So that you get a nicer looking representation for standard string or map or vector or whatever, rather than just splatting out a whole bunch of incomprehensible gobbledygook. And that's something that contemporary GDB does through bringing in a Python script as well. But in the base system today, we don't have that capability. And one of the, I don't really want to talk about GDB versus LLDB too much because it's not really a valid comparison to say contemporary LLDB does so much that 10 year old GDB doesn't do. It's not really a very useful discussion. But I think one of the things that's very interesting is even compared to contemporary GDB, the discussion is very much around what can one do that the other can't. And I think we'll see over the next couple of years, as we've seen with Clang and LLVM, the early discussion was, how does this compare to Clang and LLVM? How does it compare to GCC? And that's, we've largely moved past that now. We're largely talking about what are the interesting things we can do because of the way that Clang and LLVM work? And what can we build on top of that? And I think in the next couple of years, we'll see the same thing with LLDB, where we won't be comparing features or saying what isn't implemented yet. It really will be one of the cool things that we can do with LLDB because of the way it's built. And this is just a closeup of the plugins. I'm not going to go through all of it, but I've highlighted in blue the ones here that either had to be written for FreeBSD or that FreeBSD heavily relies on. And the process plugin there is probably the most important one. It provides register definitions and the concept, any sort of thing that is specific to a FreeBSD debuggy, the FreeBSD target. The platform represents running LLDB on a FreeBSD host, so things like copying files to or from the host system. I'll describe briefly how LLDB looks from actual use. So, GDB's command parser has evolved over time to have all kinds of overloaded. All the commands can take all kinds of different options, depending on what context they're in, without really knowing exactly what it is. So, for example, the breakpoint is the best example. You can set a breakpoint and without really telling it what it is, it can be a function name, it can be a file and then line number, it can be a C++ method, and it just sort of hopefully figures out what it is you mean. And LLDB, it's normal. The command parser was sort of designed from the beginning to try and be very regular and discoverable, and so all of the commands are of the form noun verb and then options and an argument. So instead of a whole bunch of overloaded breakpoint commands, it would be breakpoints that dash, dash, name, main. And this is a little bit verbose, but like GDB, you can use the shortest, unique prefix of the entire command name. But also, LLDB introduces a whole bunch of aliases so that generally speaking, the basic functionality of GDB for single-stepping or for starting a process or for setting a breakpoint, there is an alias that allows LLDB to work with your finger memory from GDB. And most of these are just direct aliases. The command works exactly the same way or doesn't take any arguments, but the breakpoint command is actually a specific, the B command, sorry, in LLDB as an alias is a specific command that's implemented to try and handle some of the overloaded options that you can provide to GDB's breakpoint command, but it really, it's a much limited set. So if you're going to use LLDB, it really is a good idea to sort of try using the, to get familiar with LLDB's native commands. And so I'm gonna give a very brief demo here. So I have here the text of Romeo and Juliet from the Gutenberg project, and this is actually an example from LLDB's website. So if you'd like to try it out, you can follow along there. And so the application here is just a simple dictionary that will read in that entire file, accept a word and then tell you if it's found in the file or not. And it builds a binary search tree from the file that you type in and then just shows you if things are found. So for example, if I type in words that I would expect to find in Romeo and Juliet, they're found. And if I type in words that would not be expected, not found, but if I type in a word that should be in there, it says, oh, it's not in there. And so that's the bug they've introduced in this hypothetical example. So you may have to bear with me if something doesn't work here because this is actually a development snapshot as I've been working through a number of issues on my working directory. But so we'll start up LLDB with our buggy example. And first we'll set a break point. There's a find word function that takes the word that the user has provided and performs the binary search. So as you'd expect with the debugger, it stopped at our break point. It's given us a little code snippet and it tells us that we stopped. The reason is a break point. What thread ID we've stopped in, the instruction pointer, our application and the function that we've stopped in and the function's arguments. We can get a back trace, et cetera. So one of the really interesting things we can do with the Python scripting is write a Python to be able to understand the same data structures that we use in our C code. So if we'd say type in script, we get a Python interpreter and I'll just cut and paste this. So tree utils is the little snippet that's provided that can understand the binary search tree that's in our code. LLDB.frame.find variable is just looking up a variable in the frame that we're stopped in and we're asking it to find the path to the word that we expect to find there. And so the Python has told us that we should go right, left, right, right, left down the tree and find the word that we wanna see. So if we look here, this is the find word function that we stopped in and we can see line 134 and line 136 are the two branches for taking the left or right branch of the tree as we search. And so I will add a Python script. So I'll set break points at the two return statements as we're gonna go through the tree. And now we can add a snippet of Python to run when we hit the break point. And it gives a quick little help discussion here or description about variables that you'll have to use in the Python that you're gonna enter. Just, and so what we're asking for in this little Python snippet is we have that path variable that we calculated using the Python version of the tree walking earlier and we're saying if the first character of the remaining path is R and we're in the right return branch, then we'll just strip that one off and continue. But if we actually take the left branch in the C code and we know we're supposed to go right to be able to get to the word that we're looking for, we'll print out a little statement and not continue. There's all of our break points that we've set. We'll disable the initial find word break point and we'll restart. Oh, and this is, there's a little bit of a race condition with IO handling in my current debug snapshot. So in this specific case, sometimes you'll see LLDB prompt came back out here. LLDB's command interpreter popped up on top of the target I'm trying to run. So I just tried again. And now I've entered Romeo again and we've stopped and printed out the text that we had in Python. It says we're going down the right branch and we should be going down the left. And if we, so we can just type script and then a one line Python if we don't want to actually enter the Python command interpreter and then quit afterwards. And it's telling us that this is what's remaining. So we had RL, RRL and we stripped off the R and then this is the path that we should still be taking but we've taken the right path. We can look at, look down the tree with the path that we've expected and there's the word that we want to find and if we say the word we're looking for that's the word we're looking for. And I mean, this is a bit of a contrived example. So, oh, there's the problem. It's, we've uppercased or lowercase the words as we've inserted them into the tree. It wouldn't actually be that easy of course but it does demonstrate the sort of power that's available through this sort of interface. Now I'll just talk very briefly about the current status of LLDB on FreeBSD. So the test suite, after a lot of work runs consistently on FreeBSD, there are build bots that are running regularly on each commit in the upstream clang LVMLDB repositories and the full test suite basically runs the tests that don't apply to FreeBSD don't but 311 tests run and all of the failures have a PR in LLVM's bugzilla. So initially, there were large classes of functionality that just didn't work. Those of all, we've moved past those sorts of things and what remains are some one or two off cases that are maybe not fully understood but there's the beginning of some debugging information in the upstream repository. And actually that's one thing that I forgot to mention earlier. I mentioned that LLVM or LLDB is under the same permissive BSD-like license as the rest of clang in LLVM but the other really big difference is that the upstream LLDB community is very helpful and very welcoming. So I started doing some initial work to get the build fixes ready and submitting a lot of patches and in very short order, they said, we're tired of committing these things for you. We'd like you to just become an LLDB committer so you can push the free BSD changes indirectly. And so it was only a matter of a few months of me submitting patches and getting things moving along that I was an LLDB committer and the rest of the LLDB upstream is very, very helpful to anyone who comes along with questions and talking about ideas for future direction or general things that people would like to implement across a variety of operating systems. In free BSD right now, AMD64 is the only target that really works and LLDB on free BSD is a perfectly capable, very usable debugger for AMD64. I said I wasn't gonna say this too much but at least as good as GDB in the base system. I-386, there's code in the tree. It doesn't actually work. It's in that same state of you can't even start a simple process and set a break point at main. And there's nothing in here I think that's particularly difficult. It's just usual 32 versus 64 bit kinds of issues so some offsets are incorrect or something along those lines. It's just that the I-386 support has been a fairly low priority for me so I haven't spent any time on it yet. Well there are more important things to fix in AMD64. MIPS is not usable as a local debugger at the moment so you can't actually run LLDB MIPS on your little MIPS device but it does actually support core files from MIPS binaries. And ARM, because Apple obviously cares an awful lot about ARM, LLDB's internals have a lot of ARM support but it hasn't been brought over for free BSD or Linux yet. 64 bit ARM support is starting to come for Linux and we'll bring that over to free BSD as well. It's early days yet but I don't think it's it won't be particularly long before LLDB is actually a workable ARM64 debugger on free BSD. Spark 64 it has some volunteer effort or sorry PowerPC has some volunteer effort and then Spark 64 and IA64 I don't know if anyone's gonna actually work on getting those working. So I've looked through this over time and it used to be that a lot of these things didn't work basically now for user land debugging LLDB is great on and again this is AMD64. The watch points are an interesting one interesting case. Most of this work is work that I've done to get these things to function. Watch points was actually contributed by another developer at a company called Zinuous so it's even in within the specific domain of LLDB on free BSD I'm not the only one doing the work. I had a Google summer of code student over this past summer working on kernel side debugging. He delivered a workable proof of concept demonstrating that yes we can against a live running on your your live system against dev mem or with kernel core dumps it will be possible and it's the project didn't really get as far as I would have liked in order to be to have something committable to the tree directly but I'll definitely take that work and refine it to have kernel core and live debugging and then on the bottom this is something that will come a little bit later. So for OS 10 kernel debugging is done using UDP over ethernet because most systems you want to debug these days don't have serial ports anymore which is the sort of traditional interface you would have used or fire wire that's all disappearing. So at least LLDB has internal support for ethernet remote debugging and it has a OS 10 back in for that only at the moment but by the time we have the stub support in FreeBSD I'll work on getting the LLDB side in. GDB protocol remote debugging it's in and it basically works it does need some more testing to find if there's any other corner cases that don't work but what's really interesting is that hasn't historically been particularly useful for FreeBSD because GDB server hasn't been workable for us. There is a project now called LLDB-GDB server which is a bit of a strange name I just call it LLGS and it is implementing the same sort of functionality so it's a debugging stub that you run on your target and the debugger connects to it over some interface and controls your user land process over that interface. It's being developed by the Google guys for Linux initially and I have done a little bit of work getting it to FreeBSD and again I think it is not yet fully working for Linux but it's very close and in very short order I'll be able to get that running on FreeBSD. So this is very important for embedded targets where you don't have an awful lot of memory and don't have a lot of CPU power. So it uses a lot of the same low level infrastructure from LLDB but doesn't bring along the Clang expression parser and all of the higher level more heavy weight functionality. One of the really neat things about LLDB is that it is inherently a cross architecture and cross OS debugger so in the same way that Clang and LLVM have support for a whole bunch of target architectures built in when you chose that compile time you can but generally speaking the entire set that supported LLDB works the same way. So what it means is I can run LLDB on my FreeBSD laptop and with that same LLDB binary I could debug a local process on my laptop. I could connect to a Linux target and do remote debugging of a Linux target or I could connect to say a FreeBSD MIPS device on my x86 laptop using the same LLDB binary. And for the most part that sort of works it's because it's not a particularly commonly used case yet there are quite a few small issues that one will run into when trying it. So really what needs to happen there is just getting a lot more testing and bug reports and as we find things that don't work they'll get fixed quickly. LLDB there's a snapshot in the base system right now. Upstream FreeBSD development on LLDB the bleeding edge is upstream. So all of my work is actually going there first now and then coming into FreeBSD after settling for a little while. But we have a snapshot in the base system it's not built by default but if you add with LLDB equals yes to source.conf and the standard build world and build kernel as well build world and install world is defined in the handbook it will give you an LLDB in your install. Clang 3.5 imports coming into FreeBSD sometime in the fairly near future and when that happens I plan to bring in a new update from LLDB upstream and enable it by default. And the last point is that Python is a little bit of a trick because we're not gonna have Python in the base system so some of the more interesting functionality wouldn't be available unless we can do something about this and what my hope is that we, right now Python in LLDB is a compile time option it's very easy to build LLDB with or without Python but it is compile time. So my hope is to move that to a runtime check and the LLDB in the base system will magically be able to use Python functionality if you've installed the port. Thank you. Any question? The main usage of LLDB especially imports the current LLDB is the machine interface that a lot of the desktop development environment use. LLDB has the same machine interface is already implemented as just planet or I don't know the question. I feel you want to use Cadevelop. I could use Cadevelop with LLDB just to use LLDB is not yet implemented. Sorry, can you? The machine interface. Yeah. The GDB machine interface is used to speak. Right, so GDB implements a machine interface which is a way for frontends to communicate with the GDB binary running. LLDB has actually had a compatible implementation of that contributed fairly recently. So LLDB also can speak the same GDB MI protocol so that various frontends that know how to speak GDB MI could talk to LLDB MI as the backend. In this case, actually, this is a screenshot from an IDE called CodeLite which builds on free BSD. It doesn't include the LLDB support yet but the integration that the CodeLite guys have done uses the LLDB native API. So LibLLDB just links into CodeLite for their use. But yes, any of the other kinds of GDB frontends that speak the MI protocol could use LLDB as well. Hi, since you mentioned that there were watchpoints there. Other was hardware watchpoints or? Yeah, hardware watchpoints. Perfect, thank you. Just a question. As you had to implement all the free BSD specific part, how much work is it? I'm from MINIX, so we were kind of thinking of importing it. That's a very difficult question to answer. A lot more than I expected. For a few reasons. So as I said, when I started, a lot of things were in fairly poor shape and there was actually a bunch of internal LLDB functionality that I had to fix up for our specific use case that was even independent of free BSD or Linux. It was just core internal bits that didn't work properly. So it's a little bit hard to say. Like I said, I've been working on LLDB off and on since the beginning of 2013. I think though that with the way things are progressing at LLDB now, it actually isn't gonna be all that difficult for additional projects to do a port because there's been a whole bunch of refactoring that has been going on and is still going on to clean up a lot of interfaces. So it becomes much, much more clear where you need to plug in OS specific functionality. And also I think the effort to bring on the next BSD port is much less than what I went through with this part. So that BSD, there is some initial build infrastructure in there and basically to be able to run LLDB on an FBSD host but not the actual P-Trace interface. But I don't think it's a huge project anymore. Okay, thank you. Well, hi. Is it possible that you connect LLDB with the open on chip debugger? Well, obviously it supports plenty of JTAX and it will be quite useful. So I mean, I think that open OCD just exports the GDB remote protocol, doesn't it? So LLDB can speak that protocol. So that should all just work. It may, there may be reasons that it might be interesting to actually use other interfaces to open OCD. But I think in general, it would work the same way GDB does of speaking the GDB remote debugging protocol. Okay, thank you, Ed. Thank you. Okay.