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