4 On demand symbols can be enabled in LLDB for projects that generate debug info
5 for more than what is required by a normal debug session. Some build systems
6 enable debug information for all binaries and can end up producing many
7 gigabytes of debug information. This amount of debug information can greatly
8 increase debug session load times and can slow developer productivity when the
9 debug information isn't indexed. It can also cause expression evaluation to
10 be slow when types from all of the binaries have full debug info as each module
11 is queried for very common types, or global name lookups fail due to a mistyped
17 When should I consider enabling this feature?
18 ---------------------------------------------
20 Anyone that has a build system that produces debug information for many
21 binaries that are not all required when you want to focus on debugging a few of
22 the produced binaries. Some build systems enable debug info as a project wide
23 switch and the build system files that control how things are built are not
24 easy to modify to produce debug info for only a small subset of the files being
25 linked. If your debug session startup times are slow because of too much debug
26 info, this feature might help you be more productive during daily use.
28 How do I enable on demand symbols?
29 ----------------------------------
31 This feature is enabled using a LLDB setting:
36 (lldb) settings set symbols.load-on-demand true
38 Users can also put this command into their ~/.lldbinit file so it is always
41 How does this feature work?
42 ---------------------------
44 This feature works by selectively enabling debug information for modules that
45 the user focuses on. It is designed to be enabled and work without the user
46 having to set any other settings and will try and determine when to enable
47 debug info access from the modules automatically. All modules with debug info
48 start off with their debug information turned off for expensive name and type
49 lookups. The debug information for line tables are always left enabled to allow
50 users to reliably set breakpoints by file and line. As the user debugs their
51 target, some simple things can cause module to get its debug information
52 enabled (called hydration):
53 - Setting a file and line breakpoint
54 - Any PC from any stack frame that maps to a module
55 - Setting a breakpoint by function name
56 - Finding a global variable by name
58 Since most users set breakpoints by file and line, this is an easy way for
59 people to inform the debugger that they want focus on this module. Breakpoints
60 by file and line are always enabled when on demand symbols is being used. Line
61 tables in debug information are cheap to parse and breakpoints will be able to
62 be set in any module that has debug info. Setting breakpoints by file and line
63 acts as one of the primary ways to enable debug info for a module as it is
64 the most common way to stop your program at interesting areas of your code.
66 Once the user hits a breakpoint, or stops the program for any other reason,
67 like a crash, assertion or signal, the debugger will calculate the stack frames
68 for one or more threads. Any stack frames whose PC value is contained within
69 one of a module's sections will have its debug information enabled. This allows
70 us to enable debug information for the areas of code that the user is stopped
71 in and will allow only the important subset of modules to have their debug
74 On demand symbol loading tries to avoid indexing the names within the debug
75 information and makes a few tradeoffs to allow name matching of functions and
76 globals without having to always index all of the debug information.
77 Setting breakpoints by function name can work, but we try to avoid using
78 debug information by relying on the symbol tables from a module. Debug
79 information name indexing is one of the most expensive operations that we are
80 trying to avoid with the on demand symbol loading so this is one of the main
81 tradeoffs of this feature. When setting a breakpoint by function name, if the
82 symbol table contains a match, the debug inforamation will be enabled for that
83 module and the query will be completed using the debug information. This does
84 mean that setting breakpoints on inline function names can fail for modules
85 that have debug info, but no matches in the symbol table since inlined
86 functions don't exist in symbol tables. When using on demand symbol loading it
87 is encouraged to not strip the symbol tables of local symbols as this will
88 allow users to set breakpoints on all concrete functions reliably. Stripped
89 symbol tables have their local symbols removed from the symbol table which
90 means that static functions and non exported function will not appear in the
91 symbol tables. This can cause breakpoint setting by function name to fail when
92 previously it wouldn't fail.
94 Global variable lookups rely on the same methodology as breakpoint setting by
95 function name: we use the symbol tables to find a match first if debug
96 information isn't enabled for a module. If we find a match in the symbol table
97 for a global variable lookup, we will enable debug inforamation and complete
98 the query using the debug information. It is encouraged to not strip your
99 symbol tables with this features as static variables and other non exported
100 globals will not appear in the symbol table and can lead to matches not being
103 What other things might fail?
104 -----------------------------
106 The on demand symbol loading feature tries to limit expensive name lookups
107 within debug inforamtion. As such, some lookups by name might fail when they
108 wouldn't when this feature is not eabled:
109 - Setting breakpoints by function name for inlined functions
110 - Type lookups when the expression parser requests types by name
111 - Global variable lookups by name when the name of the variable is stripped
113 Setting breakpoints by function name can fail for inline function because this
114 information is only contained in the debug information. No symbols are created
115 for inlined functions unless there is a concrete copy of the inlined function
116 in that same module. As a result, we might not end up stopping at all inlined
117 functions when requested with this feature enabled. Setting file and line
118 breakpoints are a good way still use on demand symbol loading effectively
119 and still being able to stop at inline function invocations.
121 The expression parser often tries to lookup types by name when the user types
122 an expression. These are some of the most costly parts of expression evaluation
123 as the user can type something like "iterator" as part of their expression and
124 this can result in matches from all STL types in all modules. These kinds of
125 global type lookup queries can cause thousands of results to be found if debug
126 information is enabled. The way that most debug information is created these
127 days has the type information inlined into each module. Typically each module
128 will contain full type definitions in the debug info for any types that are
129 used in code. This means that when you type an expression when stopped, you
130 have debug information for all of the variables, arguments and global variables
131 in your current stack frame and we should be able to find type that are
132 important by using only the modules that have their debug information enabled.
134 The expression parser can also be asked to display global variables and they
135 can be looked up by name. For this feature to work reliably with on demand
136 symbol loading enabled, just don't strip your symbol tables and the expression
137 parser should have no problem finding your variables. Most global variables
138 that are exported will still be in your symbol table if it is stripped, but
139 static variables and non exported globals will not be.
141 Can I troubleshoot issues when I believe this feature is impeding my debugging?
142 -------------------------------------------------------------------------------
144 Logging has been added that can be enabled to help notify our engineers when
145 something is not producing results when this feature is enabled. This logging
146 can be enabled during a debug session and can be sent to the LLDB engineers
147 to help troubleshoot these situation. To enable logging, type the following
152 (lldb) log enable -f /tmp/ondemand.txt lldb on-demand
154 When the logging is enabled, we get full visibility into each query that would
155 have produced results if this feature were not enabled and will allow us to
156 troublshoot issues. Enabling this logging before an expression, setting a
157 breakpoint by name, or doing a type lookup can help us see the patterns that
158 cause failures and will help us improve this feature.