4 The following is a mostly unordered set of the ideas for improvements to the
5 LLDB debugger. Some are fairly deep, some would require less effort.
10 Speed up type realization in lldb
11 ---------------------------------
13 The type of problem I'm addressing here is the situation where you are
14 debugging a large program (lldb built with debug clang/swift will do) and you
15 go to print a simple expression, and lldb goes away for 30 seconds. When you
16 sample it, it is always busily churning through all the CU's in the world
17 looking for something. The problem isn't that looking for something in
18 particular is slow, but rather that we somehow turned an bounded search (maybe
19 a subtype of "std::string" into an unbounded search (all things with the name
20 of that subtype.) Or didn't stop when we got a reasonable answer proximate to
21 the context of the search, but let the search leak out globally. And quite
22 likely there are other issues that I haven't guessed yet. But if you end up
23 churning though 3 or 4 Gig of debug info, that's going to be slow no matter how
24 well written your debug reader is...
26 My guess is the work will be more in the general symbol lookup than in the
27 DWARF parser in particular, but it may be a combination of both.
29 As a user debugging a largish program, this is the most obvious lameness of
32 Symbol name completion in the expression parser
33 -----------------------------------------------
35 This is the other obvious lameness of lldb. You can do:
39 (lldb) frame var foo.b
41 and we will tell you it is "foo.bar". But you can't do that in the expression
42 parser. This will require collaboration with the clang/swift folks to get the
43 right extension points in the compiler. And whatever they are, lldb will need
44 use them to tell the compiler about what names are available. It will be
45 important to avoid the pitfalls of #1 where we wander into the entire DWARF
48 Make a high speed asynchronous communication channel
49 ----------------------------------------------------
51 All lldb debugging nowadays is done by talking to a debug agent. We used the
52 gdb-remote protocol because that is universal, and good enough, and you have to
53 support it anyway since so many little devices & JTAG's and VM's etc support
54 it. But it is really old, not terribly high performance, and can't really
55 handle sending or receiving messages while the process is supposedly running.
56 It should have compression built in, remove the hand-built checksums and rely
57 on the robust communication protocols we always have nowadays, allow for
58 out-of-order requests/replies, allow for reconnecting to a temporarily
59 disconnected debug session, regularize all of the packet formatting into JSON
60 or BSON or whatever while including a way to do large binary transfers. It must
61 be possible to come up with something faster, and better tunable for the many
62 communications pathways we end up supporting.
64 Fix local variable lookup in the lldb expression parser
65 -------------------------------------------------------
67 The injection of local variables into the clang expression parser is
68 currently done incorrectly - it happens too late in the lookup. This results
69 in namespace variables & functions, same named types and ivars shadowing
70 locals when it should be the other way around. An attempt was made to fix
71 this by manually inserting all the visible local variables into wrapper
72 function in the expression text. This mostly gets the job done but that
73 method means you have to realize all the types and locations of all local
74 variables for even the simplest of expressions, and when run on large
75 programs (e.g. lldb) it would cause unacceptable delays. And it was very
76 fragile since an error in realizing any of the locals would cause all
77 expressions run in that context to fail. We need to fix this by adjusting
78 the points where name lookup calls out to lldb in clang.
80 Support calling SB & commands everywhere and support non-stop debugging
81 -----------------------------------------------------------------------
83 There is a fairly ad-hoc system to handle when it is safe to run SB API's and
84 command line commands. This is actually a bit of a tricky problem, since we
85 allow access to the command line and SB API from some funky places in lldb. The
86 Operating System plugins are the most obvious instance, since they get run
87 right after lldb is told by debugserver that the process has stopped, but
88 before it has finished collating the information from the stop for presentation
89 to the higher levels. But breakpoint callbacks have some of the same problems,
90 and other things like the scripted stepping operations and any fancier
91 extension points we want to add to the debugger are going to be hard to
92 implement robustly till we work on a finer-grained and more explicit control
93 over who gets to control the process state.
95 We also won't have any chance of supporting non-stop debugging - which is a
96 useful mode for programs that have a lot of high-priority or real-time worker
97 threads - until we get this sorted out.
99 Finish the language abstraction and remove all the unnecessary API's
100 --------------------------------------------------------------------
102 An important part of making lldb a more useful "debugger toolkit" as opposed to
103 a C/C++/ObjC/Swift debugger is to have a clean abstraction for language
104 support. We did most, but not all, of the physical separation. We need to
105 finish that. And then by force of necessity the API's really look like the
106 interface to a C++ type system with a few swift bits added on. How you would
107 go about adding a new language is unclear and much more trouble than it is
108 worth at present. But if we made this nice, we could add a lot of value to
109 other language projects.
111 Add some syntax to generate data formatters from type definitions
112 -----------------------------------------------------------------
114 Uses of the data formatters fall into two types. There are data formatters for
115 types where the structure elements pretty much tell you how to present the
116 data, you just need a little expression language to express how to turn them
117 into what the user expects to see. Then there are the ones (like pretty much
118 all our Foundation/AppKit/UIKit formatters) that use deep magic to figure out
119 how the type is actually laid out. The latter are pretty much always going to
120 have to be done by hand.
122 But for the ones where the information is expressed in the fields, it would be
123 great to have a way to express the instructions to produce summaries and
124 children in some form you could embed next to the types and have the compiler
125 produce a byte code form of the instructions and then make that available to
126 lldb along with the library. This isn't as simple as having clang run over the
127 headers and produce something from the types directly. After all, clang has no
128 way of knowing that the interesting thing about a std::vector is the elements
129 that you get by calling size (for the summary) and [] for the elements. But it
130 shouldn't be hard to come up with a generic markup to express this.
132 Allow the expression parser to access dynamic type/data formatter information
133 -----------------------------------------------------------------------------
135 This seems like a smaller one. The symptom is your object is Foo child of
136 Bar, and in the Locals view you see all the fields of Foo, but because the
137 static type of the object is Bar, you can't see any of the fields of Foo.
138 But if you could get this working, you could hijack the mechanism to make
139 the results of the value object summaries/synthetic children available to
140 expressions. And if you can do that, you could add other properties to an
141 object externally (through Python or some other extension point) and then
142 have these also available in the expression parser. You could use this to
143 express invariants for data structures, or other more advanced uses of types
146 Another version of this is to allow access to synthetic children in the
147 expression parser. Otherwise you end up in situations like:
151 (lldb) print return_a_foo()
152 (SomeVectorLikeType) $1 = {
164 (lldb) print return_a_foo()[2]
166 fails because the expression parser doesn't know anything about the
167 array-like nature of SomeVectorLikeType that it gets from the synthetic
170 Recover thread information lazily
171 ---------------------------------
173 LLDB stores all the user intentions for a thread in the ThreadPlans stored in
174 the Thread class. That allows us to reliably implement a very natural model for
175 users moving through a debug session. For example, if step-over stops at a
176 breakpoint in an function in a younger region of the stack, continue will
177 complete the step-over rather than having to manually step out. But that means
178 that it is important that the Thread objects live as long as the Threads they
179 represent. For programs with many threads, but only one that you are debugging,
180 that makes stepping less efficient, since now you have to fetch the thread list
181 on every step or stepping doesn't work correctly. This is especially an issue
182 when the threads are provided by an Operating System plugin, where it may take
183 non-trivial work to reconstruct the thread list. It would be better to fetch
184 threads lazily but keep "unseen" threads in a holding area, and only retire
185 them when we know we've fetched the whole thread list and ensured they are no
188 Make Python-backed commands first class citizens
189 ------------------------------------------------
191 As it stands, Python commands have no way to advertise their options. They are
192 required to parse their arguments by hand. That leads to inconsistency, and
193 more importantly means they can't take advantage of auto-generated help and
194 command completion. This leaves python-backed commands feeling worse than
197 As part of this job, it would also be great to hook automatically hook the
198 "type" of an option value or argument (e.g. eArgTypeShlibName) to sensible
199 default completers. You need to be able to over-ride this in more complicated
200 scenarios (like in "break set" where the presence of a "-s" option limits the
201 search for completion of a "-n" option.) But in common cases it is unnecessary
202 busy-work to have to supply the completer AND the type. If this worked, then it
203 would be easier for Python commands to also get correct completers.
205 Reimplement the command interpreter commands using the SB API
206 -------------------------------------------------------------
208 Currently, all the CommandObject::DoExecute methods are implemented using the
209 lldb_private API's. That generally means that there's code that gets duplicated
210 between the CommandObject and the SB API that does roughly the same thing. We
211 would reduce this code duplication, present a single coherent face to the users
212 of lldb, and keep ourselves more honest about what we need in the SB API's if
213 we implemented the CommandObjects::DoExecute methods using the SB API's.
215 BTW, it is only the way it was much easier to develop lldb if it had a
216 functioning command-line early on. So we did that first, and developed the SB
217 API's when lldb was more mature. There's no good technical reason to have the
218 commands use the lldb_private API's.
220 Documentation and better examples
221 ---------------------------------
223 We need to put the lldb syntax docs in the tutorial somewhere that is more
224 easily accessible. On suggestion is to add non-command based help to the help
225 system, and then have a "help lldb" or "help syntax" type command with this
226 info. Be nice if the non-command based help could be hierarchical so you could
229 There's a fair bit of docs about the SB API's, but it is spotty. Some classes
230 are well documented in the Python "help (lldb.SBWhatever)" and some are not.
232 We need more conceptual docs. And we need more examples. And we could provide a
233 clean pluggable example for using LLDB standalone from Python. The
234 process_events.py is a start of this, but it just handles process events, and
235 it is really a quick sketch not a polished expandable proto-tool.
237 Make a more accessible plugin architecture for lldb
238 ---------------------------------------------------
240 Right now, you can only use the Python or SB API's to extend an extant lldb.
241 You can't implement any of the actual lldb Plugins as plugins. That means
242 anybody that wants to add new Object file/Process/Language etc support has to
243 build and distribute their own lldb. This is tricky because the API's the
244 plugins use are currently not stable (and recently have been changing quite a
245 lot.) We would have to define a subset of lldb_private that you could use, and
246 some way of telling whether the plugins were compatible with the lldb. But
247 long-term, making this sort of extension possible will make lldb more appealing
248 for research and 3rd party uses.
250 Use instruction emulation to reduce the overhead for breakpoints
251 ----------------------------------------------------------------
253 At present, breakpoints are implemented by inserting a trap instruction, then
254 when the trap is hit, replace the trap with the actual instruction and single
255 step. Then swap back and continue. This causes problems for read only text, and
256 also means that no-stop debugging must either stop all threads briefly to handle
257 this two-step or risk missing some breakpoint hits. If you emulated the
258 instruction and wrote back the results, you wouldn't have these problems, and
259 it would also save a stop per breakpoint hit. Since we use breakpoints to
260 implement stepping, this savings could be significant on slow connections.
262 Use the JIT to speed up conditional breakpoint evaluation
263 ---------------------------------------------------------
265 We already JIT and cache the conditional expressions for breakpoints for the C
266 family of languages, so we aren't re-compiling every time you hit the
267 breakpoint. And if we couldn't IR interpret the expression, we leave the JIT'ed
268 code in place for reuse. But it would be even better if we could also insert
269 the "stop or not" decision into the code at the breakpoint, so you would only
270 actually stop the process when the condition was true. Greg's idea was that if
271 you had a conditional breakpoint set when you started the debug session, Xcode
272 could rebuild and insert enough no-ops that we could instrument the breakpoint
273 site and call the conditional expression, and only trap if the conditional was
276 Broaden the idea in "target stop-hook" to cover more events in the debugger
277 ---------------------------------------------------------------------------
279 Shared library loads, command execution, User directed memory/register reads
280 and writes are all places where you would reasonably want to hook into the
283 Mock classes for testing
284 ------------------------
286 We need "ProcessMock" and "ObjectFileMock" and the like. These would be real
287 plugin implementations for their underlying lldb classes, with the addition
288 that you can prime them from some sort of text based input files. For classes
289 that manage changes over time (like process) you would need to program the
290 state at StopPoint 0, StopPoint 1, etc. These could then be used for testing
291 reactions to complex threading problems & the like, and also for simulating
292 hard-to-test environments (like bare board debugging).
294 Expression parser needs syntax for "{symbol,type} A in CU B.cpp"
295 ----------------------------------------------------------------
297 Sometimes you need to specify non-visible or ambiguous types to the expression
298 parser. We were planning to do $b_dot_cpp$A or something like. You might want
299 to specify a static in a function, in a source file, or in a shared library. So
300 the syntax should support all these.
302 Add a "testButDontAbort" style test to the UnitTest framework
303 -------------------------------------------------------------
305 The way we use unittest now (maybe this is the only way it can work, I don't
306 know) you can't report a real failure and continue with the test. That is
307 appropriate in some cases: if I'm supposed to hit breakpoint A before I
308 evaluate an expression, and don't hit breakpoint A, the test should fail. But
309 it means that if I want to test five different expressions, I can either do it
310 in one test, which is good because it means I only have to fire up one process,
311 attach to it, and get it to a certain point. But it also means if the first
312 test fails, the other four don't even get run. So though at first we wrote a
313 bunch of test like this, as time went on we switched more to writing "one at a
314 time" tests because they were more robust against a single failure. That makes
315 the test suite run much more slowly. It would be great to add a
316 "test_but_dont_abort" variant of the tests, then we could gang tests that all
317 drive to the same place and do similar things. As an added benefit, it would
318 allow us to be more thorough in writing tests, since each test would have lower
321 Convert the dotest style tests to use lldbutil.run_to_source_breakpoint
322 -----------------------------------------------------------------------
324 run_to_source_breakpoint & run_to_name_breakpoint provide a compact API that
325 does in one line what the first 10 or 20 lines of most of the old tests now do
326 by hand. Using these functions makes tests much more readable, and by
327 centralizing common functionality will make maintaining the testsuites easier
328 in the future. This is more of a finger exercise, and perhaps best implemented
329 by a rule like: "If you touch a test case, and it isn't using
330 run_to_source_breakpoint, please make it do so".
332 Unify Watchpoint's & Breakpoints
333 --------------------------------
335 Option handling isn't shared, and more importantly the PerformAction's have a
336 lot of duplicated common code, most of which works less well on the Watchpoint
342 This is kind of a holy grail, it's hard to support for complex apps (many
343 threads, shared memory, etc.) But it would be SO nice to have...
348 By this I mean allowing some threads in the target program to run while
349 stopping other threads. This is supported in name in lldb at present, but lldb
350 makes the assumption "If I get a stop, I won't get another stop unless I
351 actually run the program." in a bunch of places so getting it to work reliably
352 will be some a good bit of work. And figuring out how to present this in the UI
358 We did this in gdb without a real JIT. The implementation shouldn't be that
359 hard, especially if you can build the executable for fix and continue. The
360 tricky part is how to verify that the user can only do the kinds of fixes that
361 are safe to do. No changing object sizes is easy to detect, but there were many
362 more subtle changes (function you are fixing is on the stack...) that take more
363 work to prevent. And then you have to explain these conditions the user in some
366 Unified IR interpreter
367 ----------------------
369 Currently IRInterpreter implements a portion of the LLVM IR, but it doesn't
370 handle vector data types and there are plenty of instructions it also doesn't
371 support. Conversely, lli supports most of LLVM's IR but it doesn't handle
372 remote memory and its function calling support is very rudimentary. It would be
373 useful to unify these and make the IR interpreter -- both for LLVM and LLDB --
374 better. An alternate strategy would be simply to JIT into the current process
375 but have callbacks for non-stack memory access.
377 Teach lldb to predict exception propagation at the throw site
378 -------------------------------------------------------------
380 There are a bunch of places in lldb where we need to know at the point where an
381 exception is thrown, what frame will catch the exception.
383 For instance, if an expression throws an exception, we need to know whether the
384 exception will be caught in the course of the expression evaluation. If so it
385 would be safe to let the expression continue. But since we would destroy the
386 state of the thread if we let the exception escape the expression, we currently
387 stop the expression evaluation if we see a throw. If we knew where it would be
388 caught we could distinguish these two cases.
390 Similarly, when you step over a call that throws, you want to stop at the throw
391 point if you know the exception will unwind past the frame you were stepping in,
392 but it would annoying to have the step abort every time an exception was thrown.
393 If we could predict the catching frame, we could do this right.
395 And of course, this would be a useful piece of information to display when stopped
398 Add predicates to the nodes of settings
399 ---------------------------------------
401 It would be very useful to be able to give values to settings that are dependent
402 on the triple, or executable name, for targets, or on whether a process is local
403 or remote, or on the name of a thread, etc. The original intent (and there is
404 a sketch of this in the settings parsing code) was to be able to say:
408 (lldb) settings set target{arch=x86_64}.process.thread{name=foo}...
410 The exact details are still to be worked out, however.
412 Resurrect Type Validators
413 -------------------------
415 This half-implemented feature was removed in
416 https://reviews.llvm.org/D71310 but the general idea might still be
417 useful: Type Validators look at a ValueObject, and make sure that
418 there is nothing semantically wrong with the object's contents to
419 easily catch corrupted data.