[llvm] Minimal unwinding information (DWARF CFI) checker (PR #145633)

AmirHossein PashaeeHir via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 26 11:17:53 PDT 2025


================
@@ -0,0 +1,144 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/UnwindInfoChecker/UnwindInfoState.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
+#include "llvm/MC/MCDwarf.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FormatVariadic.h"
+#include <cassert>
+#include <optional>
+
+using namespace llvm;
+
+std::optional<dwarf::UnwindTable::const_iterator>
+DWARFCFIState::getCurrentUnwindRow() const {
+  if (!Table.size())
+    return std::nullopt;
+
+  return --Table.end();
+}
+
+void DWARFCFIState::update(const MCCFIInstruction &Directive) {
+  auto MaybeCFIP = convert(Directive);
+  if (!MaybeCFIP) {
+    Context->reportError(
+        Directive.getLoc(),
+        "couldn't apply this directive to the unwinding information state");
+  }
+  auto CFIP = *MaybeCFIP;
+
+  auto MaybeCurrentRow = getCurrentUnwindRow();
+  dwarf::UnwindRow Row = MaybeCurrentRow.has_value()
+                             ? *(MaybeCurrentRow.value())
+                             : dwarf::UnwindRow();
+  dwarf::UnwindTable::RowContainer NewRows;
+  if (Error Err = parseRows(CFIP, Row, nullptr).moveInto(NewRows)) {
+    Context->reportError(
+        Directive.getLoc(),
+        formatv("could not parse this CFI directive due to: {0}",
+                toString(std::move(Err))));
+
+    // Proceed the analysis by ignoring this CFI directive.
+    return;
+  }
+  Table.insert(Table.end(), NewRows.begin(), NewRows.end());
+  Table.push_back(Row);
----------------
amsen20 wrote:

I added documentation to the function. in short:

`parseRows` updates the argument `CurrRow` by applying `CFIP` instructions to it. But in between it might need to add a couple of rows to the unwind table. These rows are returned. So what is happening is that we first add the preceding rows and then we add the new final row. 

Also, `NewRow` is copied so it's the same as the last row but when updated it doesn't update the table's last element.

The new code is:
```C++
// This is a copy of the last row of the table (or a new empty row), its value
  // will be updated by `parseRows`.
  dwarf::UnwindRow NewRow = MaybeCurrentRow.has_value()
                                ? *(MaybeCurrentRow.value())
                                : dwarf::UnwindRow();

  // `parseRows` updates the current row by applying the `CFIProgram` to it.
  // During this process, it may create multiple rows that should be placed in
  // the unwinding table, preceding the newly updated row and following the
  // previous rows. These middle rows are stored in `PrecedingRows`.
  dwarf::UnwindTable::RowContainer PrecedingRows;
  if (Error Err = parseRows(CFIP, NewRow, nullptr).moveInto(PrecedingRows)) {
    Context->reportError(
        Directive.getLoc(),
        formatv("could not parse this CFI directive due to: {0}",
                toString(std::move(Err))));

    // Proceed the analysis by ignoring this CFI directive.
    return;
  }
  ````
  

https://github.com/llvm/llvm-project/pull/145633


More information about the llvm-commits mailing list