File indexing completed on 2026-05-10 08:43:41
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H
0010 #define LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H
0011
0012 #include "llvm/ADT/ArrayRef.h"
0013 #include "llvm/ADT/SmallString.h"
0014 #include "llvm/ADT/iterator.h"
0015 #include "llvm/DebugInfo/DWARF/DWARFExpression.h"
0016 #include "llvm/Support/Error.h"
0017 #include "llvm/TargetParser/Triple.h"
0018 #include <map>
0019 #include <memory>
0020 #include <vector>
0021
0022 namespace llvm {
0023
0024 class raw_ostream;
0025 class DWARFDataExtractor;
0026 class MCRegisterInfo;
0027 struct DIDumpOptions;
0028
0029 namespace dwarf {
0030
0031 constexpr uint32_t InvalidRegisterNumber = UINT32_MAX;
0032
0033
0034
0035
0036 class UnwindLocation {
0037 public:
0038 enum Location {
0039
0040 Unspecified,
0041
0042 Undefined,
0043
0044
0045
0046 Same,
0047
0048
0049
0050 CFAPlusOffset,
0051
0052
0053
0054
0055 RegPlusOffset,
0056
0057
0058
0059
0060 DWARFExpr,
0061
0062
0063 Constant,
0064 };
0065
0066 private:
0067 Location Kind;
0068 uint32_t RegNum;
0069 int32_t Offset;
0070 std::optional<uint32_t> AddrSpace;
0071
0072 std::optional<DWARFExpression> Expr;
0073
0074 bool Dereference;
0075
0076
0077
0078
0079 UnwindLocation(Location K)
0080 : Kind(K), RegNum(InvalidRegisterNumber), Offset(0),
0081 AddrSpace(std::nullopt), Dereference(false) {}
0082
0083 UnwindLocation(Location K, uint32_t Reg, int32_t Off,
0084 std::optional<uint32_t> AS, bool Deref)
0085 : Kind(K), RegNum(Reg), Offset(Off), AddrSpace(AS), Dereference(Deref) {}
0086
0087 UnwindLocation(DWARFExpression E, bool Deref)
0088 : Kind(DWARFExpr), RegNum(InvalidRegisterNumber), Offset(0), Expr(E),
0089 Dereference(Deref) {}
0090
0091 public:
0092
0093
0094
0095 static UnwindLocation createUnspecified();
0096
0097
0098 static UnwindLocation createUndefined();
0099
0100 static UnwindLocation createSame();
0101
0102
0103
0104
0105
0106
0107
0108 static UnwindLocation createIsCFAPlusOffset(int32_t Off);
0109 static UnwindLocation createAtCFAPlusOffset(int32_t Off);
0110
0111
0112
0113
0114
0115
0116
0117
0118 static UnwindLocation
0119 createIsRegisterPlusOffset(uint32_t Reg, int32_t Off,
0120 std::optional<uint32_t> AddrSpace = std::nullopt);
0121 static UnwindLocation
0122 createAtRegisterPlusOffset(uint32_t Reg, int32_t Off,
0123 std::optional<uint32_t> AddrSpace = std::nullopt);
0124
0125
0126
0127 static UnwindLocation createIsDWARFExpression(DWARFExpression Expr);
0128 static UnwindLocation createAtDWARFExpression(DWARFExpression Expr);
0129 static UnwindLocation createIsConstant(int32_t Value);
0130
0131 Location getLocation() const { return Kind; }
0132 uint32_t getRegister() const { return RegNum; }
0133 int32_t getOffset() const { return Offset; }
0134 uint32_t getAddressSpace() const {
0135 assert(Kind == RegPlusOffset && AddrSpace);
0136 return *AddrSpace;
0137 }
0138 int32_t getConstant() const { return Offset; }
0139
0140
0141
0142 void setRegister(uint32_t NewRegNum) { RegNum = NewRegNum; }
0143
0144
0145
0146 void setOffset(int32_t NewOffset) { Offset = NewOffset; }
0147
0148
0149
0150 void setConstant(int32_t Value) { Offset = Value; }
0151
0152 std::optional<DWARFExpression> getDWARFExpressionBytes() const {
0153 return Expr;
0154 }
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167 void dump(raw_ostream &OS, DIDumpOptions DumpOpts) const;
0168
0169 bool operator==(const UnwindLocation &RHS) const;
0170 };
0171
0172 raw_ostream &operator<<(raw_ostream &OS, const UnwindLocation &R);
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182 class RegisterLocations {
0183 std::map<uint32_t, UnwindLocation> Locations;
0184
0185 public:
0186
0187
0188
0189
0190
0191
0192 std::optional<UnwindLocation> getRegisterLocation(uint32_t RegNum) const {
0193 auto Pos = Locations.find(RegNum);
0194 if (Pos == Locations.end())
0195 return std::nullopt;
0196 return Pos->second;
0197 }
0198
0199
0200
0201
0202
0203
0204 void setRegisterLocation(uint32_t RegNum, const UnwindLocation &Location) {
0205 Locations.erase(RegNum);
0206 Locations.insert(std::make_pair(RegNum, Location));
0207 }
0208
0209
0210
0211
0212 void removeRegisterLocation(uint32_t RegNum) { Locations.erase(RegNum); }
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225 void dump(raw_ostream &OS, DIDumpOptions DumpOpts) const;
0226
0227
0228 bool hasLocations() const { return !Locations.empty(); }
0229
0230 size_t size() const { return Locations.size(); }
0231
0232 bool operator==(const RegisterLocations &RHS) const {
0233 return Locations == RHS.Locations;
0234 }
0235 };
0236
0237 raw_ostream &operator<<(raw_ostream &OS, const RegisterLocations &RL);
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255 class UnwindRow {
0256
0257
0258 std::optional<uint64_t> Address;
0259 UnwindLocation CFAValue;
0260 RegisterLocations RegLocs;
0261
0262 public:
0263 UnwindRow() : CFAValue(UnwindLocation::createUnspecified()) {}
0264
0265
0266 bool hasAddress() const { return Address.has_value(); }
0267
0268
0269
0270
0271
0272 uint64_t getAddress() const { return *Address; }
0273
0274
0275
0276
0277
0278 void setAddress(uint64_t Addr) { Address = Addr; }
0279
0280
0281
0282
0283
0284
0285
0286 void slideAddress(uint64_t Offset) { *Address += Offset; }
0287 UnwindLocation &getCFAValue() { return CFAValue; }
0288 const UnwindLocation &getCFAValue() const { return CFAValue; }
0289 RegisterLocations &getRegisterLocations() { return RegLocs; }
0290 const RegisterLocations &getRegisterLocations() const { return RegLocs; }
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306 void dump(raw_ostream &OS, DIDumpOptions DumpOpts,
0307 unsigned IndentLevel = 0) const;
0308 };
0309
0310 raw_ostream &operator<<(raw_ostream &OS, const UnwindRow &Row);
0311
0312 class CFIProgram;
0313 class CIE;
0314 class FDE;
0315
0316
0317
0318
0319
0320
0321 class UnwindTable {
0322 public:
0323 using RowContainer = std::vector<UnwindRow>;
0324 using iterator = RowContainer::iterator;
0325 using const_iterator = RowContainer::const_iterator;
0326
0327 size_t size() const { return Rows.size(); }
0328 iterator begin() { return Rows.begin(); }
0329 const_iterator begin() const { return Rows.begin(); }
0330 iterator end() { return Rows.end(); }
0331 const_iterator end() const { return Rows.end(); }
0332 const UnwindRow &operator[](size_t Index) const {
0333 assert(Index < size());
0334 return Rows[Index];
0335 }
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351 void dump(raw_ostream &OS, DIDumpOptions DumpOpts,
0352 unsigned IndentLevel = 0) const;
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362 static Expected<UnwindTable> create(const CIE *Cie);
0363
0364
0365
0366
0367
0368
0369
0370
0371
0372 static Expected<UnwindTable> create(const FDE *Fde);
0373
0374 private:
0375 RowContainer Rows;
0376
0377
0378 std::optional<uint64_t> EndAddress;
0379
0380
0381
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393
0394
0395 Error parseRows(const CFIProgram &CFIP, UnwindRow &CurrRow,
0396 const RegisterLocations *InitialLocs);
0397 };
0398
0399 raw_ostream &operator<<(raw_ostream &OS, const UnwindTable &Rows);
0400
0401
0402
0403
0404
0405
0406
0407 class CFIProgram {
0408 public:
0409 static constexpr size_t MaxOperands = 3;
0410 typedef SmallVector<uint64_t, MaxOperands> Operands;
0411
0412
0413
0414
0415 struct Instruction {
0416 Instruction(uint8_t Opcode) : Opcode(Opcode) {}
0417
0418 uint8_t Opcode;
0419 Operands Ops;
0420
0421 std::optional<DWARFExpression> Expression;
0422
0423 Expected<uint64_t> getOperandAsUnsigned(const CFIProgram &CFIP,
0424 uint32_t OperandIdx) const;
0425
0426 Expected<int64_t> getOperandAsSigned(const CFIProgram &CFIP,
0427 uint32_t OperandIdx) const;
0428 };
0429
0430 using InstrList = std::vector<Instruction>;
0431 using iterator = InstrList::iterator;
0432 using const_iterator = InstrList::const_iterator;
0433
0434 iterator begin() { return Instructions.begin(); }
0435 const_iterator begin() const { return Instructions.begin(); }
0436 iterator end() { return Instructions.end(); }
0437 const_iterator end() const { return Instructions.end(); }
0438
0439 unsigned size() const { return (unsigned)Instructions.size(); }
0440 bool empty() const { return Instructions.empty(); }
0441 uint64_t codeAlign() const { return CodeAlignmentFactor; }
0442 int64_t dataAlign() const { return DataAlignmentFactor; }
0443 Triple::ArchType triple() const { return Arch; }
0444
0445 CFIProgram(uint64_t CodeAlignmentFactor, int64_t DataAlignmentFactor,
0446 Triple::ArchType Arch)
0447 : CodeAlignmentFactor(CodeAlignmentFactor),
0448 DataAlignmentFactor(DataAlignmentFactor),
0449 Arch(Arch) {}
0450
0451
0452
0453
0454
0455 Error parse(DWARFDataExtractor Data, uint64_t *Offset, uint64_t EndOffset);
0456
0457 void dump(raw_ostream &OS, DIDumpOptions DumpOpts, unsigned IndentLevel,
0458 std::optional<uint64_t> InitialLocation) const;
0459
0460 void addInstruction(const Instruction &I) { Instructions.push_back(I); }
0461
0462
0463 StringRef callFrameString(unsigned Opcode) const;
0464
0465 private:
0466 std::vector<Instruction> Instructions;
0467 const uint64_t CodeAlignmentFactor;
0468 const int64_t DataAlignmentFactor;
0469 Triple::ArchType Arch;
0470
0471
0472 void addInstruction(uint8_t Opcode) {
0473 Instructions.push_back(Instruction(Opcode));
0474 }
0475
0476
0477 void addInstruction(uint8_t Opcode, uint64_t Operand1) {
0478 Instructions.push_back(Instruction(Opcode));
0479 Instructions.back().Ops.push_back(Operand1);
0480 }
0481
0482
0483 void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) {
0484 Instructions.push_back(Instruction(Opcode));
0485 Instructions.back().Ops.push_back(Operand1);
0486 Instructions.back().Ops.push_back(Operand2);
0487 }
0488
0489
0490 void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2,
0491 uint64_t Operand3) {
0492 Instructions.push_back(Instruction(Opcode));
0493 Instructions.back().Ops.push_back(Operand1);
0494 Instructions.back().Ops.push_back(Operand2);
0495 Instructions.back().Ops.push_back(Operand3);
0496 }
0497
0498
0499
0500
0501
0502
0503
0504 enum OperandType {
0505 OT_Unset,
0506 OT_None,
0507 OT_Address,
0508 OT_Offset,
0509 OT_FactoredCodeOffset,
0510 OT_SignedFactDataOffset,
0511 OT_UnsignedFactDataOffset,
0512 OT_Register,
0513 OT_AddressSpace,
0514 OT_Expression
0515 };
0516
0517
0518 static const char *operandTypeString(OperandType OT);
0519
0520
0521
0522 static ArrayRef<OperandType[MaxOperands]> getOperandTypes();
0523
0524
0525 void printOperand(raw_ostream &OS, DIDumpOptions DumpOpts,
0526 const Instruction &Instr, unsigned OperandIdx,
0527 uint64_t Operand, std::optional<uint64_t> &Address) const;
0528 };
0529
0530
0531
0532 class FrameEntry {
0533 public:
0534 enum FrameKind { FK_CIE, FK_FDE };
0535
0536 FrameEntry(FrameKind K, bool IsDWARF64, uint64_t Offset, uint64_t Length,
0537 uint64_t CodeAlign, int64_t DataAlign, Triple::ArchType Arch)
0538 : Kind(K), IsDWARF64(IsDWARF64), Offset(Offset), Length(Length),
0539 CFIs(CodeAlign, DataAlign, Arch) {}
0540
0541 virtual ~FrameEntry() = default;
0542
0543 FrameKind getKind() const { return Kind; }
0544 uint64_t getOffset() const { return Offset; }
0545 uint64_t getLength() const { return Length; }
0546 const CFIProgram &cfis() const { return CFIs; }
0547 CFIProgram &cfis() { return CFIs; }
0548
0549
0550 virtual void dump(raw_ostream &OS, DIDumpOptions DumpOpts) const = 0;
0551
0552 protected:
0553 const FrameKind Kind;
0554
0555 const bool IsDWARF64;
0556
0557
0558 const uint64_t Offset;
0559
0560
0561 const uint64_t Length;
0562
0563 CFIProgram CFIs;
0564 };
0565
0566
0567 class CIE : public FrameEntry {
0568 public:
0569
0570
0571 CIE(bool IsDWARF64, uint64_t Offset, uint64_t Length, uint8_t Version,
0572 SmallString<8> Augmentation, uint8_t AddressSize,
0573 uint8_t SegmentDescriptorSize, uint64_t CodeAlignmentFactor,
0574 int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister,
0575 SmallString<8> AugmentationData, uint32_t FDEPointerEncoding,
0576 uint32_t LSDAPointerEncoding, std::optional<uint64_t> Personality,
0577 std::optional<uint32_t> PersonalityEnc, Triple::ArchType Arch)
0578 : FrameEntry(FK_CIE, IsDWARF64, Offset, Length, CodeAlignmentFactor,
0579 DataAlignmentFactor, Arch),
0580 Version(Version), Augmentation(std::move(Augmentation)),
0581 AddressSize(AddressSize), SegmentDescriptorSize(SegmentDescriptorSize),
0582 CodeAlignmentFactor(CodeAlignmentFactor),
0583 DataAlignmentFactor(DataAlignmentFactor),
0584 ReturnAddressRegister(ReturnAddressRegister),
0585 AugmentationData(std::move(AugmentationData)),
0586 FDEPointerEncoding(FDEPointerEncoding),
0587 LSDAPointerEncoding(LSDAPointerEncoding), Personality(Personality),
0588 PersonalityEnc(PersonalityEnc) {}
0589
0590 static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_CIE; }
0591
0592 StringRef getAugmentationString() const { return Augmentation; }
0593 uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor; }
0594 int64_t getDataAlignmentFactor() const { return DataAlignmentFactor; }
0595 uint8_t getVersion() const { return Version; }
0596 uint64_t getReturnAddressRegister() const { return ReturnAddressRegister; }
0597 std::optional<uint64_t> getPersonalityAddress() const { return Personality; }
0598 std::optional<uint32_t> getPersonalityEncoding() const {
0599 return PersonalityEnc;
0600 }
0601
0602 StringRef getAugmentationData() const { return AugmentationData; }
0603
0604 uint32_t getFDEPointerEncoding() const { return FDEPointerEncoding; }
0605
0606 uint32_t getLSDAPointerEncoding() const { return LSDAPointerEncoding; }
0607
0608 void dump(raw_ostream &OS, DIDumpOptions DumpOpts) const override;
0609
0610 private:
0611
0612 const uint8_t Version;
0613 const SmallString<8> Augmentation;
0614 const uint8_t AddressSize;
0615 const uint8_t SegmentDescriptorSize;
0616 const uint64_t CodeAlignmentFactor;
0617 const int64_t DataAlignmentFactor;
0618 const uint64_t ReturnAddressRegister;
0619
0620
0621 const SmallString<8> AugmentationData;
0622 const uint32_t FDEPointerEncoding;
0623 const uint32_t LSDAPointerEncoding;
0624 const std::optional<uint64_t> Personality;
0625 const std::optional<uint32_t> PersonalityEnc;
0626 };
0627
0628
0629 class FDE : public FrameEntry {
0630 public:
0631 FDE(bool IsDWARF64, uint64_t Offset, uint64_t Length, uint64_t CIEPointer,
0632 uint64_t InitialLocation, uint64_t AddressRange, CIE *Cie,
0633 std::optional<uint64_t> LSDAAddress, Triple::ArchType Arch)
0634 : FrameEntry(FK_FDE, IsDWARF64, Offset, Length,
0635 Cie ? Cie->getCodeAlignmentFactor() : 0,
0636 Cie ? Cie->getDataAlignmentFactor() : 0, Arch),
0637 CIEPointer(CIEPointer), InitialLocation(InitialLocation),
0638 AddressRange(AddressRange), LinkedCIE(Cie), LSDAAddress(LSDAAddress) {}
0639
0640 ~FDE() override = default;
0641
0642 const CIE *getLinkedCIE() const { return LinkedCIE; }
0643 uint64_t getCIEPointer() const { return CIEPointer; }
0644 uint64_t getInitialLocation() const { return InitialLocation; }
0645 uint64_t getAddressRange() const { return AddressRange; }
0646 std::optional<uint64_t> getLSDAAddress() const { return LSDAAddress; }
0647
0648 void dump(raw_ostream &OS, DIDumpOptions DumpOpts) const override;
0649
0650 static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_FDE; }
0651
0652 private:
0653
0654
0655
0656
0657 const uint64_t CIEPointer;
0658 const uint64_t InitialLocation;
0659 const uint64_t AddressRange;
0660 const CIE *LinkedCIE;
0661 const std::optional<uint64_t> LSDAAddress;
0662 };
0663
0664 }
0665
0666
0667 class DWARFDebugFrame {
0668 const Triple::ArchType Arch;
0669
0670 const bool IsEH;
0671
0672 const uint64_t EHFrameAddress;
0673
0674 std::vector<std::unique_ptr<dwarf::FrameEntry>> Entries;
0675 using iterator = pointee_iterator<decltype(Entries)::const_iterator>;
0676
0677
0678 dwarf::FrameEntry *getEntryAtOffset(uint64_t Offset) const;
0679
0680 public:
0681
0682
0683
0684
0685 DWARFDebugFrame(Triple::ArchType Arch,
0686 bool IsEH = false, uint64_t EHFrameAddress = 0);
0687 ~DWARFDebugFrame();
0688
0689
0690 void dump(raw_ostream &OS, DIDumpOptions DumpOpts,
0691 std::optional<uint64_t> Offset) const;
0692
0693
0694
0695 Error parse(DWARFDataExtractor Data);
0696
0697
0698 bool empty() const { return Entries.empty(); }
0699
0700
0701 iterator begin() const { return Entries.begin(); }
0702 iterator end() const { return Entries.end(); }
0703 iterator_range<iterator> entries() const {
0704 return iterator_range<iterator>(Entries.begin(), Entries.end());
0705 }
0706
0707 uint64_t getEHFrameAddress() const { return EHFrameAddress; }
0708 };
0709
0710 }
0711
0712 #endif