| 1 | 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(<ref_from>,<ref_to>) |
| 119 | |
| 120 | <ref_from> - "#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 | <ref_to> - "#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 | <def> - "#id=" |
| 134 | |
| 135 | Uses: |
| 136 | <def><name>:<typedef1>... |
| 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 | <def> |
| 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 | <ref> - "#id" where "#id" refers to the symbol for which the string |
| 147 | "#id=" identifies. |
| 148 | Uses: |
| 149 | <ref>:<typedef2>;<liverange>;<liverange>... |
| 150 | Defines an alias for the symbol identified by the reference |
| 151 | number ID. |
| 152 | l(<ref1>,<ref2>) |
| 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 | <liverange> - "l(<ref_from>,<ref_to>)" - 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. |