@@ -29,356 +29,6 @@ struct DIDumpOptions;
2929
3030namespace dwarf {
3131
32- constexpr uint32_t InvalidRegisterNumber = UINT32_MAX;
33-
34- // / A class that represents a location for the Call Frame Address (CFA) or a
35- // / register. This is decoded from the DWARF Call Frame Information
36- // / instructions and put into an UnwindRow.
37- class UnwindLocation {
38- public:
39- enum Location {
40- // / Not specified.
41- Unspecified,
42- // / Register is not available and can't be recovered.
43- Undefined,
44- // / Register value is in the register, nothing needs to be done to unwind
45- // / it:
46- // / reg = reg
47- Same,
48- // / Register is in or at the CFA plus an offset:
49- // / reg = CFA + offset
50- // / reg = defef(CFA + offset)
51- CFAPlusOffset,
52- // / Register or CFA is in or at a register plus offset, optionally in
53- // / an address space:
54- // / reg = reg + offset [in addrspace]
55- // / reg = deref(reg + offset [in addrspace])
56- RegPlusOffset,
57- // / Register or CFA value is in or at a value found by evaluating a DWARF
58- // / expression:
59- // / reg = eval(dwarf_expr)
60- // / reg = deref(eval(dwarf_expr))
61- DWARFExpr,
62- // / Value is a constant value contained in "Offset":
63- // / reg = Offset
64- Constant,
65- };
66-
67- private:
68- Location Kind; // / The type of the location that describes how to unwind it.
69- uint32_t RegNum; // / The register number for Kind == RegPlusOffset.
70- int32_t Offset; // / The offset for Kind == CFAPlusOffset or RegPlusOffset.
71- std::optional<uint32_t > AddrSpace; // / The address space for Kind ==
72- // / RegPlusOffset for CFA.
73- std::optional<DWARFExpression> Expr; // / The DWARF expression for Kind ==
74- // / DWARFExpression.
75- bool Dereference; // / If true, the resulting location must be dereferenced
76- // / after the location value is computed.
77-
78- // Constructors are private to force people to use the create static
79- // functions.
80- UnwindLocation (Location K)
81- : Kind(K), RegNum(InvalidRegisterNumber), Offset(0 ),
82- AddrSpace (std::nullopt ), Dereference(false ) {}
83-
84- UnwindLocation (Location K, uint32_t Reg, int32_t Off,
85- std::optional<uint32_t > AS, bool Deref)
86- : Kind(K), RegNum(Reg), Offset(Off), AddrSpace(AS), Dereference(Deref) {}
87-
88- UnwindLocation (DWARFExpression E, bool Deref)
89- : Kind(DWARFExpr), RegNum(InvalidRegisterNumber), Offset(0 ), Expr(E),
90- Dereference(Deref) {}
91-
92- public:
93- // / Create a location whose rule is set to Unspecified. This means the
94- // / register value might be in the same register but it wasn't specified in
95- // / the unwind opcodes.
96- LLVM_ABI static UnwindLocation createUnspecified ();
97- // / Create a location where the value is undefined and not available. This can
98- // / happen when a register is volatile and can't be recovered.
99- LLVM_ABI static UnwindLocation createUndefined ();
100- // / Create a location where the value is known to be in the register itself.
101- LLVM_ABI static UnwindLocation createSame ();
102- // / Create a location that is in (Deref == false) or at (Deref == true) the
103- // / CFA plus an offset. Most registers that are spilled onto the stack use
104- // / this rule. The rule for the register will use this rule and specify a
105- // / unique offset from the CFA with \a Deref set to true. This value will be
106- // / relative to a CFA value which is typically defined using the register
107- // / plus offset location. \see createRegisterPlusOffset(...) for more
108- // / information.
109- LLVM_ABI static UnwindLocation createIsCFAPlusOffset (int32_t Off);
110- LLVM_ABI static UnwindLocation createAtCFAPlusOffset (int32_t Off);
111- // / Create a location where the saved value is in (Deref == false) or at
112- // / (Deref == true) a regiser plus an offset and, optionally, in the specified
113- // / address space (used mostly for the CFA).
114- // /
115- // / The CFA is usually defined using this rule by using the stack pointer or
116- // / frame pointer as the register, with an offset that accounts for all
117- // / spilled registers and all local variables in a function, and Deref ==
118- // / false.
119- LLVM_ABI static UnwindLocation
120- createIsRegisterPlusOffset (uint32_t Reg, int32_t Off,
121- std::optional<uint32_t > AddrSpace = std::nullopt );
122- LLVM_ABI static UnwindLocation
123- createAtRegisterPlusOffset (uint32_t Reg, int32_t Off,
124- std::optional<uint32_t > AddrSpace = std::nullopt );
125- // / Create a location whose value is the result of evaluating a DWARF
126- // / expression. This allows complex expressions to be evaluated in order to
127- // / unwind a register or CFA value.
128- LLVM_ABI static UnwindLocation createIsDWARFExpression (DWARFExpression Expr);
129- LLVM_ABI static UnwindLocation createAtDWARFExpression (DWARFExpression Expr);
130- LLVM_ABI static UnwindLocation createIsConstant (int32_t Value);
131-
132- Location getLocation () const { return Kind; }
133- uint32_t getRegister () const { return RegNum; }
134- int32_t getOffset () const { return Offset; }
135- uint32_t getAddressSpace () const {
136- assert (Kind == RegPlusOffset && AddrSpace);
137- return *AddrSpace;
138- }
139- int32_t getConstant () const { return Offset; }
140- bool getDereference () const { return Dereference; }
141-
142- // / Some opcodes will modify the CFA location's register only, so we need
143- // / to be able to modify the CFA register when evaluating DWARF Call Frame
144- // / Information opcodes.
145- void setRegister (uint32_t NewRegNum) { RegNum = NewRegNum; }
146- // / Some opcodes will modify the CFA location's offset only, so we need
147- // / to be able to modify the CFA offset when evaluating DWARF Call Frame
148- // / Information opcodes.
149- void setOffset (int32_t NewOffset) { Offset = NewOffset; }
150- // / Some opcodes modify a constant value and we need to be able to update
151- // / the constant value (DW_CFA_GNU_window_save which is also known as
152- // DW_CFA_AARCH64_negate_ra_state).
153- void setConstant (int32_t Value) { Offset = Value; }
154-
155- std::optional<DWARFExpression> getDWARFExpressionBytes () const {
156- return Expr;
157- }
158- // / Dump a location expression as text and use the register information if
159- // / some is provided.
160- // /
161- // / \param OS the stream to use for output.
162- // /
163- // / \param MRI register information that helps emit register names insteead
164- // / of raw register numbers.
165- // /
166- // / \param IsEH true if the DWARF Call Frame Information is from .eh_frame
167- // / instead of from .debug_frame. This is needed for register number
168- // / conversion because some register numbers differ between the two sections
169- // / for certain architectures like x86.
170- LLVM_ABI void dump (raw_ostream &OS, DIDumpOptions DumpOpts) const ;
171-
172- LLVM_ABI bool operator ==(const UnwindLocation &RHS) const ;
173- };
174-
175- LLVM_ABI raw_ostream &operator <<(raw_ostream &OS, const UnwindLocation &R);
176-
177- // / A class that can track all registers with locations in a UnwindRow object.
178- // /
179- // / Register locations use a map where the key is the register number and the
180- // / the value is a UnwindLocation.
181- // /
182- // / The register maps are put into a class so that all register locations can
183- // / be copied when parsing the unwind opcodes DW_CFA_remember_state and
184- // / DW_CFA_restore_state.
185- class RegisterLocations {
186- std::map<uint32_t , UnwindLocation> Locations;
187-
188- public:
189- // / Return the location for the register in \a RegNum if there is a location.
190- // /
191- // / \param RegNum the register number to find a location for.
192- // /
193- // / \returns A location if one is available for \a RegNum, or std::nullopt
194- // / otherwise.
195- std::optional<UnwindLocation> getRegisterLocation (uint32_t RegNum) const {
196- auto Pos = Locations.find (RegNum);
197- if (Pos == Locations.end ())
198- return std::nullopt ;
199- return Pos->second ;
200- }
201-
202- // / Set the location for the register in \a RegNum to \a Location.
203- // /
204- // / \param RegNum the register number to set the location for.
205- // /
206- // / \param Location the UnwindLocation that describes how to unwind the value.
207- void setRegisterLocation (uint32_t RegNum, const UnwindLocation &Location) {
208- Locations.erase (RegNum);
209- Locations.insert (std::make_pair (RegNum, Location));
210- }
211-
212- // / Removes any rule for the register in \a RegNum.
213- // /
214- // / \param RegNum the register number to remove the location for.
215- void removeRegisterLocation (uint32_t RegNum) { Locations.erase (RegNum); }
216-
217- // / Dump all registers + locations that are currently defined in this object.
218- // /
219- // / \param OS the stream to use for output.
220- // /
221- // / \param MRI register information that helps emit register names insteead
222- // / of raw register numbers.
223- // /
224- // / \param IsEH true if the DWARF Call Frame Information is from .eh_frame
225- // / instead of from .debug_frame. This is needed for register number
226- // / conversion because some register numbers differ between the two sections
227- // / for certain architectures like x86.
228- LLVM_ABI void dump (raw_ostream &OS, DIDumpOptions DumpOpts) const ;
229-
230- // / Returns true if we have any register locations in this object.
231- bool hasLocations () const { return !Locations.empty (); }
232-
233- size_t size () const { return Locations.size (); }
234-
235- bool operator ==(const RegisterLocations &RHS) const {
236- return Locations == RHS.Locations ;
237- }
238- };
239-
240- LLVM_ABI raw_ostream &operator <<(raw_ostream &OS, const RegisterLocations &RL);
241-
242- // / A class that represents a single row in the unwind table that is decoded by
243- // / parsing the DWARF Call Frame Information opcodes.
244- // /
245- // / The row consists of an optional address, the rule to unwind the CFA and all
246- // / rules to unwind any registers. If the address doesn't have a value, this
247- // / row represents the initial instructions for a CIE. If the address has a
248- // / value the UnwindRow represents a row in the UnwindTable for a FDE. The
249- // / address is the first address for which the CFA location and register rules
250- // / are valid within a function.
251- // /
252- // / UnwindRow objects are created by parsing opcodes in the DWARF Call Frame
253- // / Information and UnwindRow objects are lazily populated and pushed onto a
254- // / stack in the UnwindTable when evaluating this state machine. Accessors are
255- // / needed for the address, CFA value, and register locations as the opcodes
256- // / encode a state machine that produces a sorted array of UnwindRow objects
257- // / \see UnwindTable.
258- class UnwindRow {
259- // / The address will be valid when parsing the instructions in a FDE. If
260- // / invalid, this object represents the initial instructions of a CIE.
261- std::optional<uint64_t > Address; // /< Address for row in FDE, invalid for CIE.
262- UnwindLocation CFAValue; // /< How to unwind the Call Frame Address (CFA).
263- RegisterLocations RegLocs; // /< How to unwind all registers in this list.
264-
265- public:
266- UnwindRow () : CFAValue(UnwindLocation::createUnspecified()) {}
267-
268- // / Returns true if the address is valid in this object.
269- bool hasAddress () const { return Address.has_value (); }
270-
271- // / Get the address for this row.
272- // /
273- // / Clients should only call this function after verifying it has a valid
274- // / address with a call to \see hasAddress().
275- uint64_t getAddress () const { return *Address; }
276-
277- // / Set the address for this UnwindRow.
278- // /
279- // / The address represents the first address for which the CFAValue and
280- // / RegLocs are valid within a function.
281- void setAddress (uint64_t Addr) { Address = Addr; }
282-
283- // / Offset the address for this UnwindRow.
284- // /
285- // / The address represents the first address for which the CFAValue and
286- // / RegLocs are valid within a function. Clients must ensure that this object
287- // / already has an address (\see hasAddress()) prior to calling this
288- // / function.
289- void slideAddress (uint64_t Offset) { *Address += Offset; }
290- UnwindLocation &getCFAValue () { return CFAValue; }
291- const UnwindLocation &getCFAValue () const { return CFAValue; }
292- RegisterLocations &getRegisterLocations () { return RegLocs; }
293- const RegisterLocations &getRegisterLocations () const { return RegLocs; }
294-
295- // / Dump the UnwindRow to the stream.
296- // /
297- // / \param OS the stream to use for output.
298- // /
299- // / \param MRI register information that helps emit register names insteead
300- // / of raw register numbers.
301- // /
302- // / \param IsEH true if the DWARF Call Frame Information is from .eh_frame
303- // / instead of from .debug_frame. This is needed for register number
304- // / conversion because some register numbers differ between the two sections
305- // / for certain architectures like x86.
306- // /
307- // / \param IndentLevel specify the indent level as an integer. The UnwindRow
308- // / will be output to the stream preceded by 2 * IndentLevel number of spaces.
309- LLVM_ABI void dump (raw_ostream &OS, DIDumpOptions DumpOpts,
310- unsigned IndentLevel = 0 ) const ;
311- };
312-
313- LLVM_ABI raw_ostream &operator <<(raw_ostream &OS, const UnwindRow &Row);
314-
315- // / A class that contains all UnwindRow objects for an FDE or a single unwind
316- // / row for a CIE. To unwind an address the rows, which are sorted by start
317- // / address, can be searched to find the UnwindRow with the lowest starting
318- // / address that is greater than or equal to the address that is being looked
319- // / up.
320- class UnwindTable {
321- public:
322- using RowContainer = std::vector<UnwindRow>;
323- using iterator = RowContainer::iterator;
324- using const_iterator = RowContainer::const_iterator;
325-
326- UnwindTable (RowContainer &&Rows) : Rows(std::move(Rows)) {}
327-
328- size_t size () const { return Rows.size (); }
329- iterator begin () { return Rows.begin (); }
330- const_iterator begin () const { return Rows.begin (); }
331- iterator end () { return Rows.end (); }
332- const_iterator end () const { return Rows.end (); }
333- const UnwindRow &operator [](size_t Index) const {
334- assert (Index < size ());
335- return Rows[Index];
336- }
337-
338- // / Dump the UnwindTable to the stream.
339- // /
340- // / \param OS the stream to use for output.
341- // /
342- // / \param MRI register information that helps emit register names instead
343- // / of raw register numbers.
344- // /
345- // / \param IsEH true if the DWARF Call Frame Information is from .eh_frame
346- // / instead of from .debug_frame. This is needed for register number
347- // / conversion because some register numbers differ between the two sections
348- // / for certain architectures like x86.
349- // /
350- // / \param IndentLevel specify the indent level as an integer. The UnwindRow
351- // / will be output to the stream preceded by 2 * IndentLevel number of spaces.
352- LLVM_ABI void dump (raw_ostream &OS, DIDumpOptions DumpOpts,
353- unsigned IndentLevel = 0 ) const ;
354-
355- private:
356- RowContainer Rows;
357- };
358-
359- // / Parse the information in the CFIProgram and update the CurrRow object
360- // / that the state machine describes.
361- // /
362- // / This function emulates the state machine described in the DWARF Call Frame
363- // / Information opcodes and will push CurrRow onto a RowContainer when needed.
364- // /
365- // / \param CFIP the CFI program that contains the opcodes from a CIE or FDE.
366- // /
367- // / \param CurrRow the current row to modify while parsing the state machine.
368- // /
369- // / \param InitialLocs If non-NULL, we are parsing a FDE and this contains
370- // / the initial register locations from the CIE. If NULL, then a CIE's
371- // / opcodes are being parsed and this is not needed. This is used for the
372- // / DW_CFA_restore and DW_CFA_restore_extended opcodes.
373- // /
374- // / \returns An error if the DWARF Call Frame Information opcodes have state
375- // / machine errors, or the accumulated rows otherwise.
376- LLVM_ABI Expected<UnwindTable::RowContainer>
377- parseRows (const CFIProgram &CFIP, UnwindRow &CurrRow,
378- const RegisterLocations *InitialLocs);
379-
380- LLVM_ABI raw_ostream &operator <<(raw_ostream &OS, const UnwindTable &Rows);
381-
38232class CIE ;
38333
38434// / Create an UnwindTable from a Common Information Entry (CIE).
0 commit comments