@@ -29,354 +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- // / Some opcodes will modify the CFA location's register only, so we need
141- // / to be able to modify the CFA register when evaluating DWARF Call Frame
142- // / Information opcodes.
143- void setRegister (uint32_t NewRegNum) { RegNum = NewRegNum; }
144- // / Some opcodes will modify the CFA location's offset only, so we need
145- // / to be able to modify the CFA offset when evaluating DWARF Call Frame
146- // / Information opcodes.
147- void setOffset (int32_t NewOffset) { Offset = NewOffset; }
148- // / Some opcodes modify a constant value and we need to be able to update
149- // / the constant value (DW_CFA_GNU_window_save which is also known as
150- // DW_CFA_AARCH64_negate_ra_state).
151- void setConstant (int32_t Value) { Offset = Value; }
152-
153- std::optional<DWARFExpression> getDWARFExpressionBytes () const {
154- return Expr;
155- }
156- // / Dump a location expression as text and use the register information if
157- // / some is provided.
158- // /
159- // / \param OS the stream to use for output.
160- // /
161- // / \param MRI register information that helps emit register names insteead
162- // / of raw register numbers.
163- // /
164- // / \param IsEH true if the DWARF Call Frame Information is from .eh_frame
165- // / instead of from .debug_frame. This is needed for register number
166- // / conversion because some register numbers differ between the two sections
167- // / for certain architectures like x86.
168- LLVM_ABI void dump (raw_ostream &OS, DIDumpOptions DumpOpts) const ;
169-
170- LLVM_ABI bool operator ==(const UnwindLocation &RHS) const ;
171- };
172-
173- LLVM_ABI raw_ostream &operator <<(raw_ostream &OS, const UnwindLocation &R);
174-
175- // / A class that can track all registers with locations in a UnwindRow object.
176- // /
177- // / Register locations use a map where the key is the register number and the
178- // / the value is a UnwindLocation.
179- // /
180- // / The register maps are put into a class so that all register locations can
181- // / be copied when parsing the unwind opcodes DW_CFA_remember_state and
182- // / DW_CFA_restore_state.
183- class RegisterLocations {
184- std::map<uint32_t , UnwindLocation> Locations;
185-
186- public:
187- // / Return the location for the register in \a RegNum if there is a location.
188- // /
189- // / \param RegNum the register number to find a location for.
190- // /
191- // / \returns A location if one is available for \a RegNum, or std::nullopt
192- // / otherwise.
193- std::optional<UnwindLocation> getRegisterLocation (uint32_t RegNum) const {
194- auto Pos = Locations.find (RegNum);
195- if (Pos == Locations.end ())
196- return std::nullopt ;
197- return Pos->second ;
198- }
199-
200- // / Set the location for the register in \a RegNum to \a Location.
201- // /
202- // / \param RegNum the register number to set the location for.
203- // /
204- // / \param Location the UnwindLocation that describes how to unwind the value.
205- void setRegisterLocation (uint32_t RegNum, const UnwindLocation &Location) {
206- Locations.erase (RegNum);
207- Locations.insert (std::make_pair (RegNum, Location));
208- }
209-
210- // / Removes any rule for the register in \a RegNum.
211- // /
212- // / \param RegNum the register number to remove the location for.
213- void removeRegisterLocation (uint32_t RegNum) { Locations.erase (RegNum); }
214-
215- // / Dump all registers + locations that are currently defined in this object.
216- // /
217- // / \param OS the stream to use for output.
218- // /
219- // / \param MRI register information that helps emit register names insteead
220- // / of raw register numbers.
221- // /
222- // / \param IsEH true if the DWARF Call Frame Information is from .eh_frame
223- // / instead of from .debug_frame. This is needed for register number
224- // / conversion because some register numbers differ between the two sections
225- // / for certain architectures like x86.
226- LLVM_ABI void dump (raw_ostream &OS, DIDumpOptions DumpOpts) const ;
227-
228- // / Returns true if we have any register locations in this object.
229- bool hasLocations () const { return !Locations.empty (); }
230-
231- size_t size () const { return Locations.size (); }
232-
233- bool operator ==(const RegisterLocations &RHS) const {
234- return Locations == RHS.Locations ;
235- }
236- };
237-
238- LLVM_ABI raw_ostream &operator <<(raw_ostream &OS, const RegisterLocations &RL);
239-
240- // / A class that represents a single row in the unwind table that is decoded by
241- // / parsing the DWARF Call Frame Information opcodes.
242- // /
243- // / The row consists of an optional address, the rule to unwind the CFA and all
244- // / rules to unwind any registers. If the address doesn't have a value, this
245- // / row represents the initial instructions for a CIE. If the address has a
246- // / value the UnwindRow represents a row in the UnwindTable for a FDE. The
247- // / address is the first address for which the CFA location and register rules
248- // / are valid within a function.
249- // /
250- // / UnwindRow objects are created by parsing opcodes in the DWARF Call Frame
251- // / Information and UnwindRow objects are lazily populated and pushed onto a
252- // / stack in the UnwindTable when evaluating this state machine. Accessors are
253- // / needed for the address, CFA value, and register locations as the opcodes
254- // / encode a state machine that produces a sorted array of UnwindRow objects
255- // / \see UnwindTable.
256- class UnwindRow {
257- // / The address will be valid when parsing the instructions in a FDE. If
258- // / invalid, this object represents the initial instructions of a CIE.
259- std::optional<uint64_t > Address; // /< Address for row in FDE, invalid for CIE.
260- UnwindLocation CFAValue; // /< How to unwind the Call Frame Address (CFA).
261- RegisterLocations RegLocs; // /< How to unwind all registers in this list.
262-
263- public:
264- UnwindRow () : CFAValue(UnwindLocation::createUnspecified()) {}
265-
266- // / Returns true if the address is valid in this object.
267- bool hasAddress () const { return Address.has_value (); }
268-
269- // / Get the address for this row.
270- // /
271- // / Clients should only call this function after verifying it has a valid
272- // / address with a call to \see hasAddress().
273- uint64_t getAddress () const { return *Address; }
274-
275- // / Set the address for this UnwindRow.
276- // /
277- // / The address represents the first address for which the CFAValue and
278- // / RegLocs are valid within a function.
279- void setAddress (uint64_t Addr) { Address = Addr; }
280-
281- // / Offset the address for this UnwindRow.
282- // /
283- // / The address represents the first address for which the CFAValue and
284- // / RegLocs are valid within a function. Clients must ensure that this object
285- // / already has an address (\see hasAddress()) prior to calling this
286- // / function.
287- void slideAddress (uint64_t Offset) { *Address += Offset; }
288- UnwindLocation &getCFAValue () { return CFAValue; }
289- const UnwindLocation &getCFAValue () const { return CFAValue; }
290- RegisterLocations &getRegisterLocations () { return RegLocs; }
291- const RegisterLocations &getRegisterLocations () const { return RegLocs; }
292-
293- // / Dump the UnwindRow to the stream.
294- // /
295- // / \param OS the stream to use for output.
296- // /
297- // / \param MRI register information that helps emit register names insteead
298- // / of raw register numbers.
299- // /
300- // / \param IsEH true if the DWARF Call Frame Information is from .eh_frame
301- // / instead of from .debug_frame. This is needed for register number
302- // / conversion because some register numbers differ between the two sections
303- // / for certain architectures like x86.
304- // /
305- // / \param IndentLevel specify the indent level as an integer. The UnwindRow
306- // / will be output to the stream preceded by 2 * IndentLevel number of spaces.
307- LLVM_ABI void dump (raw_ostream &OS, DIDumpOptions DumpOpts,
308- unsigned IndentLevel = 0 ) const ;
309- };
310-
311- LLVM_ABI raw_ostream &operator <<(raw_ostream &OS, const UnwindRow &Row);
312-
313- // / A class that contains all UnwindRow objects for an FDE or a single unwind
314- // / row for a CIE. To unwind an address the rows, which are sorted by start
315- // / address, can be searched to find the UnwindRow with the lowest starting
316- // / address that is greater than or equal to the address that is being looked
317- // / up.
318- class UnwindTable {
319- public:
320- using RowContainer = std::vector<UnwindRow>;
321- using iterator = RowContainer::iterator;
322- using const_iterator = RowContainer::const_iterator;
323-
324- UnwindTable (RowContainer &&Rows) : Rows(std::move(Rows)) {}
325-
326- size_t size () const { return Rows.size (); }
327- iterator begin () { return Rows.begin (); }
328- const_iterator begin () const { return Rows.begin (); }
329- iterator end () { return Rows.end (); }
330- const_iterator end () const { return Rows.end (); }
331- const UnwindRow &operator [](size_t Index) const {
332- assert (Index < size ());
333- return Rows[Index];
334- }
335-
336- // / Dump the UnwindTable to the stream.
337- // /
338- // / \param OS the stream to use for output.
339- // /
340- // / \param MRI register information that helps emit register names instead
341- // / of raw register numbers.
342- // /
343- // / \param IsEH true if the DWARF Call Frame Information is from .eh_frame
344- // / instead of from .debug_frame. This is needed for register number
345- // / conversion because some register numbers differ between the two sections
346- // / for certain architectures like x86.
347- // /
348- // / \param IndentLevel specify the indent level as an integer. The UnwindRow
349- // / will be output to the stream preceded by 2 * IndentLevel number of spaces.
350- LLVM_ABI void dump (raw_ostream &OS, DIDumpOptions DumpOpts,
351- unsigned IndentLevel = 0 ) const ;
352-
353- private:
354- RowContainer Rows;
355- };
356-
357- // / Parse the information in the CFIProgram and update the CurrRow object
358- // / that the state machine describes.
359- // /
360- // / This function emulates the state machine described in the DWARF Call Frame
361- // / Information opcodes and will push CurrRow onto a RowContainer when needed.
362- // /
363- // / \param CFIP the CFI program that contains the opcodes from a CIE or FDE.
364- // /
365- // / \param CurrRow the current row to modify while parsing the state machine.
366- // /
367- // / \param InitialLocs If non-NULL, we are parsing a FDE and this contains
368- // / the initial register locations from the CIE. If NULL, then a CIE's
369- // / opcodes are being parsed and this is not needed. This is used for the
370- // / DW_CFA_restore and DW_CFA_restore_extended opcodes.
371- // /
372- // / \returns An error if the DWARF Call Frame Information opcodes have state
373- // / machine errors, or the accumulated rows otherwise.
374- LLVM_ABI Expected<UnwindTable::RowContainer>
375- parseRows (const CFIProgram &CFIP, UnwindRow &CurrRow,
376- const RegisterLocations *InitialLocs);
377-
378- LLVM_ABI raw_ostream &operator <<(raw_ostream &OS, const UnwindTable &Rows);
379-
38032class CIE ;
38133
38234// / Create an UnwindTable from a Common Information Entry (CIE).
0 commit comments