[llvm] [NFC] Remove UnwindTable dependency on CIE, and FDE (PR #142520)
AmirHossein PashaeeHir via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 19 17:14:00 PDT 2025
https://github.com/amsen20 updated https://github.com/llvm/llvm-project/pull/142520
>From 055492de6590cfad05704997de59dd4429bc0a32 Mon Sep 17 00:00:00 2001
From: Amirhossein Pashaeehir <amirhosseinp at google.com>
Date: Mon, 2 Jun 2025 22:31:07 +0000
Subject: [PATCH 1/4] Remove UnwindTable dependency on CIE, and FDE
(transitively on llvm/Object)
For creating new UnwindTable, two static methods was implemented inside it, to create an instance of it from a CIE or FDE.
This static methods are moved out of the class as a library functions.
---
.../llvm/DebugInfo/DWARF/DWARFDebugFrame.h | 65 ++++++++++---------
llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp | 14 ++--
.../DebugInfo/DWARF/DWARFDebugFrameTest.cpp | 56 ++++++++--------
3 files changed, 71 insertions(+), 64 deletions(-)
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
index 051ea6e11e351..d48d3b628a9c8 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
@@ -311,9 +311,6 @@ class UnwindRow {
LLVM_ABI raw_ostream &operator<<(raw_ostream &OS, const UnwindRow &Row);
-class CIE;
-class FDE;
-
/// A class that contains all UnwindRow objects for an FDE or a single unwind
/// row for a CIE. To unwind an address the rows, which are sorted by start
/// address, can be searched to find the UnwindRow with the lowest starting
@@ -334,6 +331,12 @@ class UnwindTable {
assert(Index < size());
return Rows[Index];
}
+ void insertRow(const UnwindRow &Row) { Rows.push_back(Row); }
+
+ /// Set the last address that this unwinding table refers to.
+ ///
+ /// This is used when this table is created based on a FDE.
+ void setEndAddress(uint64_t Addr) { EndAddress = Addr; }
/// Dump the UnwindTable to the stream.
///
@@ -352,32 +355,6 @@ class UnwindTable {
LLVM_ABI void dump(raw_ostream &OS, DIDumpOptions DumpOpts,
unsigned IndentLevel = 0) const;
- /// Create an UnwindTable from a Common Information Entry (CIE).
- ///
- /// \param Cie The Common Information Entry to extract the table from. The
- /// CFIProgram is retrieved from the \a Cie object and used to create the
- /// UnwindTable.
- ///
- /// \returns An error if the DWARF Call Frame Information opcodes have state
- /// machine errors, or a valid UnwindTable otherwise.
- LLVM_ABI static Expected<UnwindTable> create(const CIE *Cie);
-
- /// Create an UnwindTable from a Frame Descriptor Entry (FDE).
- ///
- /// \param Fde The Frame Descriptor Entry to extract the table from. The
- /// CFIProgram is retrieved from the \a Fde object and used to create the
- /// UnwindTable.
- ///
- /// \returns An error if the DWARF Call Frame Information opcodes have state
- /// machine errors, or a valid UnwindTable otherwise.
- LLVM_ABI static Expected<UnwindTable> create(const FDE *Fde);
-
-private:
- RowContainer Rows;
- /// The end address when data is extracted from a FDE. This value will be
- /// invalid when a UnwindTable is extracted from a CIE.
- std::optional<uint64_t> EndAddress;
-
/// Parse the information in the CFIProgram and update the CurrRow object
/// that the state machine describes.
///
@@ -395,10 +372,40 @@ class UnwindTable {
/// DW_CFA_restore and DW_CFA_restore_extended opcodes.
Error parseRows(const CFIProgram &CFIP, UnwindRow &CurrRow,
const RegisterLocations *InitialLocs);
+
+private:
+ RowContainer Rows;
+ /// The end address when data is extracted from a FDE. This value will be
+ /// invalid when a UnwindTable is extracted from a CIE.
+ std::optional<uint64_t> EndAddress;
};
LLVM_ABI raw_ostream &operator<<(raw_ostream &OS, const UnwindTable &Rows);
+class CIE;
+
+/// Create an UnwindTable from a Common Information Entry (CIE).
+///
+/// \param Cie The Common Information Entry to extract the table from. The
+/// CFIProgram is retrieved from the \a Cie object and used to create the
+/// UnwindTable.
+///
+/// \returns An error if the DWARF Call Frame Information opcodes have state
+/// machine errors, or a valid UnwindTable otherwise.
+Expected<UnwindTable> createUnwindTable(const CIE *Cie);
+
+class FDE;
+
+/// Create an UnwindTable from a Frame Descriptor Entry (FDE).
+///
+/// \param Fde The Frame Descriptor Entry to extract the table from. The
+/// CFIProgram is retrieved from the \a Fde object and used to create the
+/// UnwindTable.
+///
+/// \returns An error if the DWARF Call Frame Information opcodes have state
+/// machine errors, or a valid UnwindTable otherwise.
+Expected<UnwindTable> createUnwindTable(const FDE *Fde);
+
/// An entry in either debug_frame or eh_frame. This entry can be a CIE or an
/// FDE.
class FrameEntry {
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
index c46b14b4446f7..cf42151bb84aa 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
@@ -203,7 +203,7 @@ raw_ostream &llvm::dwarf::operator<<(raw_ostream &OS, const UnwindTable &Rows) {
return OS;
}
-Expected<UnwindTable> UnwindTable::create(const FDE *Fde) {
+Expected<UnwindTable> llvm::dwarf::createUnwindTable(const FDE *Fde) {
const CIE *Cie = Fde->getLinkedCIE();
if (Cie == nullptr)
return createStringError(errc::invalid_argument,
@@ -217,7 +217,7 @@ Expected<UnwindTable> UnwindTable::create(const FDE *Fde) {
UnwindTable UT;
UnwindRow Row;
Row.setAddress(Fde->getInitialLocation());
- UT.EndAddress = Fde->getInitialLocation() + Fde->getAddressRange();
+ UT.setEndAddress(Fde->getInitialLocation() + Fde->getAddressRange());
if (Error CieError = UT.parseRows(Cie->cfis(), Row, nullptr))
return std::move(CieError);
// We need to save the initial locations of registers from the CIE parsing
@@ -229,11 +229,11 @@ Expected<UnwindTable> UnwindTable::create(const FDE *Fde) {
// Do not add that to the unwind table.
if (Row.getRegisterLocations().hasLocations() ||
Row.getCFAValue().getLocation() != UnwindLocation::Unspecified)
- UT.Rows.push_back(Row);
+ UT.insertRow(Row);
return UT;
}
-Expected<UnwindTable> UnwindTable::create(const CIE *Cie) {
+Expected<UnwindTable> llvm::dwarf::createUnwindTable(const CIE *Cie) {
// Rows will be empty if there are no CFI instructions.
if (Cie->cfis().empty())
return UnwindTable();
@@ -246,7 +246,7 @@ Expected<UnwindTable> UnwindTable::create(const CIE *Cie) {
// Do not add that to the unwind table.
if (Row.getRegisterLocations().hasLocations() ||
Row.getCFAValue().getLocation() != UnwindLocation::Unspecified)
- UT.Rows.push_back(Row);
+ UT.insertRow(Row);
return UT;
}
@@ -605,7 +605,7 @@ void CIE::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
CFIs.dump(OS, DumpOpts, /*IndentLevel=*/1, /*InitialLocation=*/{});
OS << "\n";
- if (Expected<UnwindTable> RowsOrErr = UnwindTable::create(this))
+ if (Expected<UnwindTable> RowsOrErr = createUnwindTable(this))
RowsOrErr->dump(OS, DumpOpts, 1);
else {
DumpOpts.RecoverableErrorHandler(joinErrors(
@@ -633,7 +633,7 @@ void FDE::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
CFIs.dump(OS, DumpOpts, /*IndentLevel=*/1, InitialLocation);
OS << "\n";
- if (Expected<UnwindTable> RowsOrErr = UnwindTable::create(this))
+ if (Expected<UnwindTable> RowsOrErr = createUnwindTable(this))
RowsOrErr->dump(OS, DumpOpts, 1);
else {
DumpOpts.RecoverableErrorHandler(joinErrors(
diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFDebugFrameTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDebugFrameTest.cpp
index 2be656547c92e..2f91b1f86f6dd 100644
--- a/llvm/unittests/DebugInfo/DWARF/DWARFDebugFrameTest.cpp
+++ b/llvm/unittests/DebugInfo/DWARF/DWARFDebugFrameTest.cpp
@@ -465,9 +465,9 @@ TEST(DWARFDebugFrame, UnwindTableEmptyRows) {
EXPECT_THAT_ERROR(parseCFI(TestCIE, {}), Succeeded());
EXPECT_TRUE(TestCIE.cfis().empty());
- // Verify dwarf::UnwindTable::create() won't result in errors and
+ // Verify dwarf::createUnwindTable() won't result in errors and
// and empty rows are not added to CIE UnwindTable.
- Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestCIE);
+ Expected<dwarf::UnwindTable> RowsOrErr = dwarf::createUnwindTable(&TestCIE);
EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
const size_t ExpectedNumOfRows = 0;
EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows);
@@ -486,9 +486,9 @@ TEST(DWARFDebugFrame, UnwindTableEmptyRows) {
EXPECT_THAT_ERROR(parseCFI(TestFDE, {}), Succeeded());
EXPECT_TRUE(TestFDE.cfis().empty());
- // Verify dwarf::UnwindTable::create() won't result in errors and
+ // Verify dwarf::createUnwindTable() won't result in errors and
// and empty rows are not added to FDE UnwindTable.
- RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
+ RowsOrErr = dwarf::createUnwindTable(&TestFDE);
EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows);
}
@@ -504,9 +504,9 @@ TEST(DWARFDebugFrame, UnwindTableEmptyRows_NOPs) {
EXPECT_THAT_ERROR(parseCFI(TestCIE, {dwarf::DW_CFA_nop}), Succeeded());
EXPECT_TRUE(!TestCIE.cfis().empty());
- // Verify dwarf::UnwindTable::create() won't result in errors and
+ // Verify dwarf::createUnwindTable() won't result in errors and
// and empty rows are not added to CIE UnwindTable.
- Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestCIE);
+ Expected<dwarf::UnwindTable> RowsOrErr = dwarf::createUnwindTable(&TestCIE);
EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
const size_t ExpectedNumOfRows = 0;
EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows);
@@ -525,9 +525,9 @@ TEST(DWARFDebugFrame, UnwindTableEmptyRows_NOPs) {
EXPECT_THAT_ERROR(parseCFI(TestFDE, {dwarf::DW_CFA_nop}), Succeeded());
EXPECT_TRUE(!TestFDE.cfis().empty());
- // Verify dwarf::UnwindTable::create() won't result in errors and
+ // Verify dwarf::createUnwindTable() won't result in errors and
// and empty rows are not added to FDE UnwindTable.
- RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
+ RowsOrErr = dwarf::createUnwindTable(&TestFDE);
EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
EXPECT_EQ(RowsOrErr->size(), ExpectedNumOfRows);
}
@@ -567,7 +567,7 @@ TEST(DWARFDebugFrame, UnwindTableErrorNonAscendingFDERows) {
Succeeded());
// Verify we catch state machine error.
- Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
+ Expected<dwarf::UnwindTable> RowsOrErr = dwarf::createUnwindTable(&TestFDE);
EXPECT_THAT_ERROR(RowsOrErr.takeError(),
FailedWithMessage("DW_CFA_set_loc with adrress 0x1000 which"
" must be greater than the current row "
@@ -603,7 +603,7 @@ TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_restore_state) {
Succeeded());
// Verify we catch state machine error.
- Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
+ Expected<dwarf::UnwindTable> RowsOrErr = dwarf::createUnwindTable(&TestFDE);
EXPECT_THAT_ERROR(RowsOrErr.takeError(),
FailedWithMessage("DW_CFA_restore_state without a matching "
"previous DW_CFA_remember_state"));
@@ -639,7 +639,7 @@ TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_GNU_window_save) {
Succeeded());
// Verify we catch state machine error.
- Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
+ Expected<dwarf::UnwindTable> RowsOrErr = dwarf::createUnwindTable(&TestFDE);
EXPECT_THAT_ERROR(RowsOrErr.takeError(),
FailedWithMessage("DW_CFA opcode 0x2d is not supported for "
"architecture x86_64"));
@@ -674,7 +674,7 @@ TEST(DWARFDebugFrame, UnwindTableError_DW_CFA_def_cfa_offset) {
Succeeded());
// Verify we catch state machine error.
- Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
+ Expected<dwarf::UnwindTable> RowsOrErr = dwarf::createUnwindTable(&TestFDE);
EXPECT_THAT_ERROR(RowsOrErr.takeError(),
FailedWithMessage("DW_CFA_def_cfa_offset found when CFA "
"rule was not RegPlusOffset"));
@@ -709,7 +709,7 @@ TEST(DWARFDebugFrame, UnwindTableDefCFAOffsetSFCFAError) {
Succeeded());
// Verify we catch state machine error.
- Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
+ Expected<dwarf::UnwindTable> RowsOrErr = dwarf::createUnwindTable(&TestFDE);
EXPECT_THAT_ERROR(RowsOrErr.takeError(),
FailedWithMessage("DW_CFA_def_cfa_offset_sf found when CFA "
"rule was not RegPlusOffset"));
@@ -745,7 +745,7 @@ TEST(DWARFDebugFrame, UnwindTable_DW_CFA_def_cfa_register) {
EXPECT_THAT_ERROR(parseCFI(TestFDE, {}), Succeeded());
// Verify we catch state machine error.
- Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
+ Expected<dwarf::UnwindTable> RowsOrErr = dwarf::createUnwindTable(&TestFDE);
EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
const dwarf::UnwindTable &Rows = RowsOrErr.get();
EXPECT_EQ(Rows.size(), 1u);
@@ -817,7 +817,7 @@ TEST(DWARFDebugFrame, UnwindTableRowPushingOpcodes) {
Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
// Verify we catch state machine error.
- Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
+ Expected<dwarf::UnwindTable> RowsOrErr = dwarf::createUnwindTable(&TestFDE);
ASSERT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
const dwarf::UnwindTable &Rows = RowsOrErr.get();
EXPECT_EQ(Rows.size(), 6u);
@@ -892,7 +892,7 @@ TEST(DWARFDebugFrame, UnwindTable_DW_CFA_restore) {
Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
// Verify we catch state machine error.
- Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
+ Expected<dwarf::UnwindTable> RowsOrErr = dwarf::createUnwindTable(&TestFDE);
EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
const dwarf::UnwindTable &Rows = RowsOrErr.get();
EXPECT_EQ(Rows.size(), 2u);
@@ -955,7 +955,7 @@ TEST(DWARFDebugFrame, UnwindTable_DW_CFA_restore_extended) {
Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
// Verify we catch state machine error.
- Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
+ Expected<dwarf::UnwindTable> RowsOrErr = dwarf::createUnwindTable(&TestFDE);
EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
const dwarf::UnwindTable &Rows = RowsOrErr.get();
EXPECT_EQ(Rows.size(), 2u);
@@ -1016,7 +1016,7 @@ TEST(DWARFDebugFrame, UnwindTable_DW_CFA_offset) {
Reg3, dwarf::UnwindLocation::createAtCFAPlusOffset(8));
// Verify we catch state machine error.
- Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
+ Expected<dwarf::UnwindTable> RowsOrErr = dwarf::createUnwindTable(&TestFDE);
EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
const dwarf::UnwindTable &Rows = RowsOrErr.get();
EXPECT_EQ(Rows.size(), 1u);
@@ -1068,7 +1068,7 @@ TEST(DWARFDebugFrame, UnwindTable_DW_CFA_val_offset) {
Reg2, dwarf::UnwindLocation::createIsCFAPlusOffset(8));
// Verify we catch state machine error.
- Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
+ Expected<dwarf::UnwindTable> RowsOrErr = dwarf::createUnwindTable(&TestFDE);
EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
const dwarf::UnwindTable &Rows = RowsOrErr.get();
EXPECT_EQ(Rows.size(), 1u);
@@ -1113,7 +1113,7 @@ TEST(DWARFDebugFrame, UnwindTable_DW_CFA_nop) {
Reg1, dwarf::UnwindLocation::createAtCFAPlusOffset(-8));
// Verify we catch state machine error.
- Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
+ Expected<dwarf::UnwindTable> RowsOrErr = dwarf::createUnwindTable(&TestFDE);
EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
const dwarf::UnwindTable &Rows = RowsOrErr.get();
EXPECT_EQ(Rows.size(), 1u);
@@ -1203,7 +1203,7 @@ TEST(DWARFDebugFrame, UnwindTable_DW_CFA_remember_state) {
Reg3, dwarf::UnwindLocation::createAtCFAPlusOffset(-24));
// Verify we catch state machine error.
- Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
+ Expected<dwarf::UnwindTable> RowsOrErr = dwarf::createUnwindTable(&TestFDE);
EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
const dwarf::UnwindTable &Rows = RowsOrErr.get();
EXPECT_EQ(Rows.size(), 5u);
@@ -1270,7 +1270,7 @@ TEST(DWARFDebugFrame, UnwindTable_DW_CFA_undefined) {
dwarf::UnwindLocation::createUndefined());
// Verify we catch state machine error.
- Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
+ Expected<dwarf::UnwindTable> RowsOrErr = dwarf::createUnwindTable(&TestFDE);
EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
const dwarf::UnwindTable &Rows = RowsOrErr.get();
EXPECT_EQ(Rows.size(), 1u);
@@ -1314,7 +1314,7 @@ TEST(DWARFDebugFrame, UnwindTable_DW_CFA_same_value) {
VerifyLocs.setRegisterLocation(Reg1, dwarf::UnwindLocation::createSame());
// Verify we catch state machine error.
- Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
+ Expected<dwarf::UnwindTable> RowsOrErr = dwarf::createUnwindTable(&TestFDE);
EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
const dwarf::UnwindTable &Rows = RowsOrErr.get();
EXPECT_EQ(Rows.size(), 1u);
@@ -1360,7 +1360,7 @@ TEST(DWARFDebugFrame, UnwindTable_DW_CFA_register) {
Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
// Verify we catch state machine error.
- Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
+ Expected<dwarf::UnwindTable> RowsOrErr = dwarf::createUnwindTable(&TestFDE);
EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
const dwarf::UnwindTable &Rows = RowsOrErr.get();
EXPECT_EQ(Rows.size(), 1u);
@@ -1412,7 +1412,7 @@ TEST(DWARFDebugFrame, UnwindTable_DW_CFA_expression) {
Reg, dwarf::UnwindLocation::createAtDWARFExpression(Expr));
// Verify we catch state machine error.
- Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
+ Expected<dwarf::UnwindTable> RowsOrErr = dwarf::createUnwindTable(&TestFDE);
EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
const dwarf::UnwindTable &Rows = RowsOrErr.get();
EXPECT_EQ(Rows.size(), 1u);
@@ -1464,7 +1464,7 @@ TEST(DWARFDebugFrame, UnwindTable_DW_CFA_val_expression) {
Reg, dwarf::UnwindLocation::createIsDWARFExpression(Expr));
// Verify we catch state machine error.
- Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
+ Expected<dwarf::UnwindTable> RowsOrErr = dwarf::createUnwindTable(&TestFDE);
EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
const dwarf::UnwindTable &Rows = RowsOrErr.get();
EXPECT_EQ(Rows.size(), 1u);
@@ -1527,7 +1527,7 @@ TEST(DWARFDebugFrame, UnwindTable_DW_CFA_def_cfa) {
Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
// Verify we catch state machine error.
- Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
+ Expected<dwarf::UnwindTable> RowsOrErr = dwarf::createUnwindTable(&TestFDE);
EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
const dwarf::UnwindTable &Rows = RowsOrErr.get();
EXPECT_EQ(Rows.size(), 5u);
@@ -1625,7 +1625,7 @@ TEST(DWARFDebugFrame, UnwindTable_DW_CFA_LLVM_def_aspace_cfa) {
Reg, dwarf::UnwindLocation::createIsRegisterPlusOffset(InReg, 0));
// Verify we catch state machine error.
- Expected<dwarf::UnwindTable> RowsOrErr = dwarf::UnwindTable::create(&TestFDE);
+ Expected<dwarf::UnwindTable> RowsOrErr = dwarf::createUnwindTable(&TestFDE);
EXPECT_THAT_ERROR(RowsOrErr.takeError(), Succeeded());
const dwarf::UnwindTable &Rows = RowsOrErr.get();
EXPECT_EQ(Rows.size(), 5u);
>From 5c807f2854fbf702bb57a91ca7e63c7b3754262c Mon Sep 17 00:00:00 2001
From: Amirhossein Pashaeehir <amirhosseinp at google.com>
Date: Tue, 17 Jun 2025 20:54:21 +0000
Subject: [PATCH 2/4] Annotate the extracted UnwindTable creators with LLVM ABI
---
llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
index d48d3b628a9c8..512d8ba0e9035 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
@@ -392,7 +392,7 @@ class CIE;
///
/// \returns An error if the DWARF Call Frame Information opcodes have state
/// machine errors, or a valid UnwindTable otherwise.
-Expected<UnwindTable> createUnwindTable(const CIE *Cie);
+LLVM_ABI Expected<UnwindTable> createUnwindTable(const CIE *Cie);
class FDE;
@@ -404,7 +404,7 @@ class FDE;
///
/// \returns An error if the DWARF Call Frame Information opcodes have state
/// machine errors, or a valid UnwindTable otherwise.
-Expected<UnwindTable> createUnwindTable(const FDE *Fde);
+LLVM_ABI Expected<UnwindTable> createUnwindTable(const FDE *Fde);
/// An entry in either debug_frame or eh_frame. This entry can be a CIE or an
/// FDE.
>From ceadfb139b27067cfd996824f3e3d9e3c2faa24a Mon Sep 17 00:00:00 2001
From: Amirhossein Pashaeehir <amirhosseinp at google.com>
Date: Wed, 18 Jun 2025 18:42:54 +0000
Subject: [PATCH 3/4] Remove unused EndAddress field
---
llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h | 8 --------
llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp | 1 -
2 files changed, 9 deletions(-)
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
index 512d8ba0e9035..0fdc81656f3f1 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
@@ -333,11 +333,6 @@ class UnwindTable {
}
void insertRow(const UnwindRow &Row) { Rows.push_back(Row); }
- /// Set the last address that this unwinding table refers to.
- ///
- /// This is used when this table is created based on a FDE.
- void setEndAddress(uint64_t Addr) { EndAddress = Addr; }
-
/// Dump the UnwindTable to the stream.
///
/// \param OS the stream to use for output.
@@ -375,9 +370,6 @@ class UnwindTable {
private:
RowContainer Rows;
- /// The end address when data is extracted from a FDE. This value will be
- /// invalid when a UnwindTable is extracted from a CIE.
- std::optional<uint64_t> EndAddress;
};
LLVM_ABI raw_ostream &operator<<(raw_ostream &OS, const UnwindTable &Rows);
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
index cf42151bb84aa..aa7f73c4fa4d4 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
@@ -217,7 +217,6 @@ Expected<UnwindTable> llvm::dwarf::createUnwindTable(const FDE *Fde) {
UnwindTable UT;
UnwindRow Row;
Row.setAddress(Fde->getInitialLocation());
- UT.setEndAddress(Fde->getInitialLocation() + Fde->getAddressRange());
if (Error CieError = UT.parseRows(Cie->cfis(), Row, nullptr))
return std::move(CieError);
// We need to save the initial locations of registers from the CIE parsing
>From f793f3e8ba78fd5e9b67c42b69ea47b55e7e6818 Mon Sep 17 00:00:00 2001
From: Amirhossein Pashaeehir <amirhosseinp at google.com>
Date: Fri, 20 Jun 2025 00:13:44 +0000
Subject: [PATCH 4/4] Make parseRows a standalone function instead of method of
UnwindTable
---
.../llvm/DebugInfo/DWARF/DWARFDebugFrame.h | 44 ++++++++++---------
llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp | 40 +++++++++++------
2 files changed, 50 insertions(+), 34 deletions(-)
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
index 0fdc81656f3f1..e05cd67fa1cd4 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
@@ -322,6 +322,8 @@ class UnwindTable {
using iterator = RowContainer::iterator;
using const_iterator = RowContainer::const_iterator;
+ UnwindTable(RowContainer Rows) : Rows(Rows) {}
+
size_t size() const { return Rows.size(); }
iterator begin() { return Rows.begin(); }
const_iterator begin() const { return Rows.begin(); }
@@ -331,13 +333,12 @@ class UnwindTable {
assert(Index < size());
return Rows[Index];
}
- void insertRow(const UnwindRow &Row) { Rows.push_back(Row); }
/// Dump the UnwindTable to the stream.
///
/// \param OS the stream to use for output.
///
- /// \param MRI register information that helps emit register names insteead
+ /// \param MRI register information that helps emit register names instead
/// of raw register numbers.
///
/// \param IsEH true if the DWARF Call Frame Information is from .eh_frame
@@ -350,28 +351,31 @@ class UnwindTable {
LLVM_ABI void dump(raw_ostream &OS, DIDumpOptions DumpOpts,
unsigned IndentLevel = 0) const;
- /// Parse the information in the CFIProgram and update the CurrRow object
- /// that the state machine describes.
- ///
- /// This is an internal implementation that emulates the state machine
- /// described in the DWARF Call Frame Information opcodes and will push
- /// CurrRow onto the Rows container when needed.
- ///
- /// \param CFIP the CFI program that contains the opcodes from a CIE or FDE.
- ///
- /// \param CurrRow the current row to modify while parsing the state machine.
- ///
- /// \param InitialLocs If non-NULL, we are parsing a FDE and this contains
- /// the initial register locations from the CIE. If NULL, then a CIE's
- /// opcodes are being parsed and this is not needed. This is used for the
- /// DW_CFA_restore and DW_CFA_restore_extended opcodes.
- Error parseRows(const CFIProgram &CFIP, UnwindRow &CurrRow,
- const RegisterLocations *InitialLocs);
-
private:
RowContainer Rows;
};
+/// Parse the information in the CFIProgram and update the CurrRow object
+/// that the state machine describes.
+///
+/// This function emulates the state machine described in the DWARF Call Frame
+/// Information opcodes and will push CurrRow onto a RowContainer when needed.
+///
+/// \param CFIP the CFI program that contains the opcodes from a CIE or FDE.
+///
+/// \param CurrRow the current row to modify while parsing the state machine.
+///
+/// \param InitialLocs If non-NULL, we are parsing a FDE and this contains
+/// the initial register locations from the CIE. If NULL, then a CIE's
+/// opcodes are being parsed and this is not needed. This is used for the
+/// DW_CFA_restore and DW_CFA_restore_extended opcodes.
+///
+/// \returns An error if the DWARF Call Frame Information opcodes have state
+/// machine errors, or the accumulated rows otherwise.
+LLVM_ABI Expected<UnwindTable::RowContainer>
+parseRows(const CFIProgram &CFIP, UnwindRow &CurrRow,
+ const RegisterLocations *InitialLocs);
+
LLVM_ABI raw_ostream &operator<<(raw_ostream &OS, const UnwindTable &Rows);
class CIE;
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
index aa7f73c4fa4d4..292f648354545 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
@@ -18,6 +18,7 @@
#include "llvm/Support/Compiler.h"
#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/Errc.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
@@ -212,45 +213,56 @@ Expected<UnwindTable> llvm::dwarf::createUnwindTable(const FDE *Fde) {
// Rows will be empty if there are no CFI instructions.
if (Cie->cfis().empty() && Fde->cfis().empty())
- return UnwindTable();
+ return UnwindTable({});
- UnwindTable UT;
+ UnwindTable::RowContainer CieRows;
UnwindRow Row;
Row.setAddress(Fde->getInitialLocation());
- if (Error CieError = UT.parseRows(Cie->cfis(), Row, nullptr))
+ if (Error CieError = parseRows(Cie->cfis(), Row, nullptr).moveInto(CieRows))
return std::move(CieError);
// We need to save the initial locations of registers from the CIE parsing
// in case we run into DW_CFA_restore or DW_CFA_restore_extended opcodes.
+ UnwindTable::RowContainer FdeRows;
const RegisterLocations InitialLocs = Row.getRegisterLocations();
- if (Error FdeError = UT.parseRows(Fde->cfis(), Row, &InitialLocs))
+ if (Error FdeError =
+ parseRows(Fde->cfis(), Row, &InitialLocs).moveInto(FdeRows))
return std::move(FdeError);
+
+ UnwindTable::RowContainer AllRows;
+ AllRows.insert(AllRows.end(), CieRows.begin(), CieRows.end());
+ AllRows.insert(AllRows.end(), FdeRows.begin(), FdeRows.end());
+
// May be all the CFI instructions were DW_CFA_nop amd Row becomes empty.
// Do not add that to the unwind table.
if (Row.getRegisterLocations().hasLocations() ||
Row.getCFAValue().getLocation() != UnwindLocation::Unspecified)
- UT.insertRow(Row);
- return UT;
+ AllRows.push_back(Row);
+ return UnwindTable(AllRows);
}
Expected<UnwindTable> llvm::dwarf::createUnwindTable(const CIE *Cie) {
// Rows will be empty if there are no CFI instructions.
if (Cie->cfis().empty())
- return UnwindTable();
+ return UnwindTable({});
- UnwindTable UT;
+ UnwindTable::RowContainer Rows;
UnwindRow Row;
- if (Error CieError = UT.parseRows(Cie->cfis(), Row, nullptr))
+ if (Error CieError = parseRows(Cie->cfis(), Row, nullptr).moveInto(Rows))
return std::move(CieError);
// May be all the CFI instructions were DW_CFA_nop amd Row becomes empty.
// Do not add that to the unwind table.
if (Row.getRegisterLocations().hasLocations() ||
Row.getCFAValue().getLocation() != UnwindLocation::Unspecified)
- UT.insertRow(Row);
- return UT;
+ Rows.push_back(Row);
+ return UnwindTable(Rows);
}
-Error UnwindTable::parseRows(const CFIProgram &CFIP, UnwindRow &Row,
- const RegisterLocations *InitialLocs) {
+Expected<UnwindTable::RowContainer>
+llvm::dwarf::parseRows(const CFIProgram &CFIP, UnwindRow &Row,
+ const RegisterLocations *InitialLocs) {
+ // All the unwinding rows parsed during processing of the CFI program.
+ UnwindTable::RowContainer Rows;
+
// State consists of CFA value and register locations.
std::vector<std::pair<UnwindLocation, RegisterLocations>> States;
for (const CFIProgram::Instruction &Inst : CFIP) {
@@ -552,7 +564,7 @@ Error UnwindTable::parseRows(const CFIProgram &CFIP, UnwindRow &Row,
break;
}
}
- return Error::success();
+ return Rows;
}
// Returns the CIE identifier to be used by the requested format.
More information about the llvm-commits
mailing list