aboutsummaryrefslogtreecommitdiff
path: root/gdb/doc/LRS
blob: eb0d711b7bee721e51ff7a54305d7520fb9aee63 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
What's LRS?
===========

LRS, or Live Range Splitting is an optimization technique which allows a user
variable to reside in different locations during different parts of a function.

For example, a variable might reside in the stack for part of a function and
in a register during a loop and in a different register during another loop.

Clearly, if a variable may reside in different locations, then the compiler
must describe to the debugger where the variable resides for any given part
of the function.

This document describes the debug format for encoding these extensions in
stabs.

Since these extensions are gcc specific, these additional symbols and stabs 
can be disabled by the gcc command option -gstabs.


GNU extensions for LRS under stabs:
===================================


range symbols:
-------------

    A range symbol will be used to mark the beginning or end of a live range
    (the range which describes where a symbol is active, or live).
    These symbols will later be referenced in the stabs for debug purposes.
    For simplicity, we'll use the terms "range_start" and "range_end" to 
    identify the range symbols which mark the beginning and end of a live 
    range respectively.

    Any text symbol which would normally appear in the symbol table (eg. a 
    function name) can be used as range symbol.  If an address is needed to 
    delimit a live range and does not match any of the values of symbols 
    which would normally appear in the symbol table, a new symbol will be 
    added to the table whose value is that address.

    The three new symbol types described below have been added for this 
    purpose.

    For efficiency, the compiler should use existing symbols as range symbols 
    whenever possible; this reduces the number of additional symbols which 
    need to be added to the symbol table.

    
New debug symbol type for defining ranges:
------------------------------------------

    range_off - contains PC function offset for start/end of a live range.
		Its location is relative to the function start and therefore 
		eliminates the need for additional relocation.

    This symbol has a values in the text section, and does not have a name.

	    NOTE: the following may not be needed but are included here just 
		in case.
	    range - contains PC value of beginning or end of a live range
		(relocs required).

	    NOTE: the following will be required if we desire LRS debugging
		to work with old style a.out stabs.
	    range_abs - contains absolute PC value of start/end of a live 
		range.  The range_abs debug symbol is provided for 
		completeness, in case there is a need to describe addresses 
		in ROM, etc.


Live range:
-----------

    The compiler and debugger view a variable with multiple homes as a primary
    symbol and aliases for that symbol.  The primary symbol describes the default
    home of the variable while aliases describe alternate homes for the variable.

    A live range defines the interval of instructions beginning with 
    range_start and ending at range_end-1, and is used to specify a range of 
    instructions where an alias is active or "live".  So, the actual end of 
    the range will be one less than the value of the range_end symbol.

    Ranges do not have to be nested. Eg. Two ranges may intersect while 
        each range contains subranges which are not in the other range.

    There does not have to be a 1-1 mapping from range_start to
        range_end symbols.  Eg. Two range_starts can share the same 
        range_end, while one symbol's range_start can be another symbol's
        range_end.

    When a variable's storage class changes (eg. from stack to register, or
	from one register to another), a new symbol entry will be added to 
	the symbol table with stabs describing the new type, and appropriate 
	live ranges refering to the variable's initial symbol index.

    For variables which are defined in the source but optimized away, a symbol
        should be emitted with the live range l(0,0).

    Live ranges for aliases of a particular variable should always be disjoint.	
	Overlapping ranges for aliases of the same variable will be treated as
	an error by the debugger, and the overlapping range will be ignored.

    If no live range information is given, the live range will be assumed to 
	span the symbol's entire lexical scope.


New stabs string identifiers:
-----------------------------

  "id" in "#id" in the following section refers to a numeric value.

  New stab syntax for live range:  l(<ref_from>,<ref_to>) 

    <ref_from> - "#id" where #id identifies the text symbol (range symbol) to
		use as the start of live range (range_start).  The value for 
		the referenced text symbol is the starting address of the 
		live range.

    <ref_to> - "#id" where #id identifies the text symbol (range symbol) to
		use as the end of live range (range_end).  The value for 
		the referenced text symbol is ONE BYTE PAST the ending 
		address of the live range.


  New stab syntax for identifying symbols.

    <def> - "#id="

	    Uses:
	      <def><name>:<typedef1>...
		  When used in front of a symbol name, "#id=" defines a
		  unique reference number for this symbol.  The reference
		  number can be used later when defining aliases for this
		  symbol.
	      <def>
		  When used as the entire stab string, "#id=" identifies this 
		  nameless symbol as being the symbol for which "#id" refers to.


    <ref> - "#id" where "#id" refers to the symbol for which the string 
		"#id=" identifies.
	    Uses:
	      <ref>:<typedef2>;<liverange>;<liverange>...
		  Defines an alias for the symbol identified by the reference
		  number ID.
	      l(<ref1>,<ref2>)
		  When used within a live range, "#id" refers to the text 
		  symbol identified by "#id=" to use as the range symbol.

    <liverange> - "l(<ref_from>,<ref_to>)" - specifies a live range for a 
		symbol.  Multiple "l" specifiers can be combined to represent 
		mutiple live ranges, separated by semicolons.




Example:
========

Consider a program of the form:

    void foo(){
      int a = ...;
      ...
      while (b--)
       c += a;
      ..
      d = a;
      ..
    }

Assume that "a" lives in the stack at offset -8, except for inside the loop where
"a" resides in register "r5".

The way to describe this is to create a stab for the variable "a" which describes
"a" as living in the stack and an alias for the variable "a" which describes it
as living in register "r5" in the loop.

Let's assume that "#1" and "#2" are symbols which bound the area where "a" lives
in a register.

The stabs to describe "a" and its alias would look like this:

        .stabs "#3=a:1",128,0,8,-8
        .stabs "#3:r1;l(#1,#2)",64,0,0,5




This design implies that the debugger will keep a chain of aliases for any
given variable with aliases and that chain will be searched first to find
out if an alias is active.  If no alias is active, then the debugger will
assume that the main variable is active.