1 |
106 |
markom |
What's LRS?
|
2 |
|
|
===========
|
3 |
|
|
|
4 |
|
|
LRS, or Live Range Splitting is an optimization technique which allows
|
5 |
|
|
a user variable to reside in different locations during different parts
|
6 |
|
|
of a function.
|
7 |
|
|
|
8 |
|
|
For example, a variable might reside in the stack for part of a function
|
9 |
|
|
and in a register during a loop and in a different register during
|
10 |
|
|
another loop.
|
11 |
|
|
|
12 |
|
|
Clearly, if a variable may reside in different locations, then the
|
13 |
|
|
compiler must describe to the debugger where the variable resides for
|
14 |
|
|
any given part of the function.
|
15 |
|
|
|
16 |
|
|
This document describes the debug format for encoding these extensions
|
17 |
|
|
in stabs.
|
18 |
|
|
|
19 |
|
|
Since these extensions are gcc specific, these additional symbols and
|
20 |
|
|
stabs can be disabled by the gcc command option -gstabs.
|
21 |
|
|
|
22 |
|
|
|
23 |
|
|
GNU extensions for LRS under stabs:
|
24 |
|
|
===================================
|
25 |
|
|
|
26 |
|
|
|
27 |
|
|
range symbols:
|
28 |
|
|
-------------
|
29 |
|
|
|
30 |
|
|
A range symbol will be used to mark the beginning or end of a
|
31 |
|
|
live range (the range which describes where a symbol is active,
|
32 |
|
|
or live). These symbols will later be referenced in the stabs for
|
33 |
|
|
debug purposes. For simplicity, we'll use the terms "range_start"
|
34 |
|
|
and "range_end" to identify the range symbols which mark the beginning
|
35 |
|
|
and end of a live range respectively.
|
36 |
|
|
|
37 |
|
|
Any text symbol which would normally appear in the symbol table
|
38 |
|
|
(eg. a function name) can be used as range symbol. If an address
|
39 |
|
|
is needed to delimit a live range and does not match any of the
|
40 |
|
|
values of symbols which would normally appear in the symbol table,
|
41 |
|
|
a new symbol will be added to the table whose value is that address.
|
42 |
|
|
|
43 |
|
|
The three new symbol types described below have been added for this
|
44 |
|
|
purpose.
|
45 |
|
|
|
46 |
|
|
For efficiency, the compiler should use existing symbols as range
|
47 |
|
|
symbols whenever possible; this reduces the number of additional
|
48 |
|
|
symbols which need to be added to the symbol table.
|
49 |
|
|
|
50 |
|
|
|
51 |
|
|
New debug symbol type for defining ranges:
|
52 |
|
|
------------------------------------------
|
53 |
|
|
|
54 |
|
|
range_off - contains PC function offset for start/end of a live range.
|
55 |
|
|
Its location is relative to the function start and therefore
|
56 |
|
|
eliminates the need for additional relocation.
|
57 |
|
|
|
58 |
|
|
This symbol has a values in the text section, and does not have a name.
|
59 |
|
|
|
60 |
|
|
NOTE: the following may not be needed but are included here just
|
61 |
|
|
in case.
|
62 |
|
|
range - contains PC value of beginning or end of a live range
|
63 |
|
|
(relocs required).
|
64 |
|
|
|
65 |
|
|
NOTE: the following will be required if we desire LRS debugging
|
66 |
|
|
to work with old style a.out stabs.
|
67 |
|
|
range_abs - contains absolute PC value of start/end of a live
|
68 |
|
|
range. The range_abs debug symbol is provided for
|
69 |
|
|
completeness, in case there is a need to describe addresses
|
70 |
|
|
in ROM, etc.
|
71 |
|
|
|
72 |
|
|
|
73 |
|
|
Live range:
|
74 |
|
|
-----------
|
75 |
|
|
|
76 |
|
|
The compiler and debugger view a variable with multiple homes as
|
77 |
|
|
a primary symbol and aliases for that symbol. The primary symbol
|
78 |
|
|
describes the default home of the variable while aliases describe
|
79 |
|
|
alternate homes for the variable.
|
80 |
|
|
|
81 |
|
|
A live range defines the interval of instructions beginning with
|
82 |
|
|
range_start and ending at range_end-1, and is used to specify a
|
83 |
|
|
range of instructions where an alias is active or "live". So,
|
84 |
|
|
the actual end of the range will be one less than the value of the
|
85 |
|
|
range_end symbol.
|
86 |
|
|
|
87 |
|
|
Ranges do not have to be nested. Eg. Two ranges may intersect while
|
88 |
|
|
each range contains subranges which are not in the other range.
|
89 |
|
|
|
90 |
|
|
There does not have to be a 1-1 mapping from range_start to
|
91 |
|
|
range_end symbols. Eg. Two range_starts can share the same
|
92 |
|
|
range_end, while one symbol's range_start can be another symbol's
|
93 |
|
|
range_end.
|
94 |
|
|
|
95 |
|
|
When a variable's storage class changes (eg. from stack to register,
|
96 |
|
|
or from one register to another), a new symbol entry will be
|
97 |
|
|
added to the symbol table with stabs describing the new type,
|
98 |
|
|
and appropriate live ranges refering to the variable's initial
|
99 |
|
|
symbol index.
|
100 |
|
|
|
101 |
|
|
For variables which are defined in the source but optimized away,
|
102 |
|
|
a symbol should be emitted with the live range l(0,0).
|
103 |
|
|
|
104 |
|
|
Live ranges for aliases of a particular variable should always
|
105 |
|
|
be disjoint. Overlapping ranges for aliases of the same variable
|
106 |
|
|
will be treated as an error by the debugger, and the overlapping
|
107 |
|
|
range will be ignored.
|
108 |
|
|
|
109 |
|
|
If no live range information is given, the live range will be assumed to
|
110 |
|
|
span the symbol's entire lexical scope.
|
111 |
|
|
|
112 |
|
|
|
113 |
|
|
New stabs string identifiers:
|
114 |
|
|
-----------------------------
|
115 |
|
|
|
116 |
|
|
"id" in "#id" in the following section refers to a numeric value.
|
117 |
|
|
|
118 |
|
|
New stab syntax for live range: l(,)
|
119 |
|
|
|
120 |
|
|
- "#id" where #id identifies the text symbol (range symbol) to
|
121 |
|
|
use as the start of live range (range_start). The value for
|
122 |
|
|
the referenced text symbol is the starting address of the
|
123 |
|
|
live range.
|
124 |
|
|
|
125 |
|
|
- "#id" where #id identifies the text symbol (range symbol) to
|
126 |
|
|
use as the end of live range (range_end). The value for
|
127 |
|
|
the referenced text symbol is ONE BYTE PAST the ending
|
128 |
|
|
address of the live range.
|
129 |
|
|
|
130 |
|
|
|
131 |
|
|
New stab syntax for identifying symbols.
|
132 |
|
|
|
133 |
|
|
- "#id="
|
134 |
|
|
|
135 |
|
|
Uses:
|
136 |
|
|
:...
|
137 |
|
|
When used in front of a symbol name, "#id=" defines a
|
138 |
|
|
unique reference number for this symbol. The reference
|
139 |
|
|
number can be used later when defining aliases for this
|
140 |
|
|
symbol.
|
141 |
|
|
|
142 |
|
|
When used as the entire stab string, "#id=" identifies this
|
143 |
|
|
nameless symbol as being the symbol for which "#id" refers to.
|
144 |
|
|
|
145 |
|
|
|
146 |
|
|
[ - "#id" where "#id" refers to the symbol for which the string]
|
147 |
|
|
"#id=" identifies.
|
148 |
|
|
Uses:
|
149 |
|
|
[:;;...]
|
150 |
|
|
Defines an alias for the symbol identified by the reference
|
151 |
|
|
number ID.
|
152 |
|
|
l(,)
|
153 |
|
|
When used within a live range, "#id" refers to the text
|
154 |
|
|
symbol identified by "#id=" to use as the range symbol.
|
155 |
|
|
|
156 |
|
|
- "l(,)" - specifies a live range for a
|
157 |
|
|
symbol. Multiple "l" specifiers can be combined to represent
|
158 |
|
|
mutiple live ranges, separated by semicolons.
|
159 |
|
|
|
160 |
|
|
|
161 |
|
|
|
162 |
|
|
|
163 |
|
|
Example:
|
164 |
|
|
========
|
165 |
|
|
|
166 |
|
|
Consider a program of the form:
|
167 |
|
|
|
168 |
|
|
void foo(){
|
169 |
|
|
int a = ...;
|
170 |
|
|
...
|
171 |
|
|
while (b--)
|
172 |
|
|
c += a;
|
173 |
|
|
..
|
174 |
|
|
d = a;
|
175 |
|
|
..
|
176 |
|
|
}
|
177 |
|
|
|
178 |
|
|
Assume that "a" lives in the stack at offset -8, except for inside the
|
179 |
|
|
loop where "a" resides in register "r5".
|
180 |
|
|
|
181 |
|
|
The way to describe this is to create a stab for the variable "a" which
|
182 |
|
|
describes "a" as living in the stack and an alias for the variable "a"
|
183 |
|
|
which describes it as living in register "r5" in the loop.
|
184 |
|
|
|
185 |
|
|
Let's assume that "#1" and "#2" are symbols which bound the area where
|
186 |
|
|
"a" lives in a register.
|
187 |
|
|
|
188 |
|
|
The stabs to describe "a" and its alias would look like this:
|
189 |
|
|
|
190 |
|
|
.stabs "#3=a:1",128,0,8,-8
|
191 |
|
|
.stabs "#3:r1;l(#1,#2)",64,0,0,5
|
192 |
|
|
|
193 |
|
|
|
194 |
|
|
This design implies that the debugger will keep a chain of aliases for
|
195 |
|
|
any given variable with aliases and that chain will be searched first
|
196 |
|
|
to find out if an alias is active. If no alias is active, then the
|
197 |
|
|
debugger will assume that the main variable is active.
|